Lisplog

Blogging in Lisp

Search

Feed Aggregator Page 670

Rendered on Wed, 21 Jul 2021 18:59:21 GMT  newer latest older 

New release of elm-charts!

via Elm - Latest posts by @cbrake Cliff Brake on Tue, 20 Jul 2021 18:41:15 GMT

Looks great! Does elm-charts supersede line-charts, or do you still recommend using line-charts?

Function equality

via Elm - Latest posts by @jfine2358 Jonathan Fine on Tue, 20 Jul 2021 18:07:42 GMT

I thank @evancz for explaining why he has implemented (==) as he had. His reasons are practical. I particularly like:

(3) [to avoid disruption due to] the eventual introduction of an equatable type

I read this as placing a high value on consistency with the math and logic definition of equality for functions. I think this is a reasonable point of view, even though the original poster describes it as overly aggressive.

If we had a partial implementation of the math-and-logic definition, then I think the development tool-chain would be a good place to use it. It could be used, as evancz says, to prove that optimizations (and refactoring simplifications) preserve the semantics of the code.

By the way, in his Structured programming with goto statements (1974), Don Knuth explores the idea of what he calls an interactive program manipulation system. This seems to be similar to what evancz described. Such a system is perhaps a refactoring assistant, much as Coq and Lean are proof assistants.

Write CLI scripts in Elm (IO Monad)

via Elm - Latest posts by @albertdahlin Albert Dahlin on Tue, 20 Jul 2021 14:31:48 GMT

My idea for this package is to make it more ergonomic to write simple CLI scripts, for example dev tools and build pipelines. I also want to make it as open as possible to allow others to implement their own I/O in nodejs. Supporting HTTP-servers is however out of scope for now.

I’m currently working on specifying the API for the following I/O modules:

  • Read / write files.
  • File system, (move, copy, delete, list etc).
  • Http client, make http requests.
  • Spawn sub processes and run shell commands.

My plan for callJs is to simplify user specific I/O implementations and allow people to experiment.

CallJs Example

CallJs is just a wrapper for communicating with the “outside” using two ports.
To create your own project specific I/O implementation my current thinking goes along these lines:

Javascript

Create a standard nodejs module that exports an Object with all your I/O functions, e.g

js/my-functions.js

module.exports = {
    addOne: function(num) {
        this.send(num + 1); // this.send is a normal Elm port
    },
}

Elm

Then create an Elm module where you supply the Encoder / Decoder for communicating with Javascript, e.g src/MyModule.elm

addOne : Int -> IO x Int
addOne n =
    IO.callJs
        "addOne"
        [ Encode.int n
        ]
        Decode.int

program : IO.Process -> IO String ()
program _ =
    ...

Put it together

When you run or compile you can add arguments to supply your I/O implementation, something like this:

elm.cli run --extend-io js/my-functions.js src/MyModule.elm

Function equality

via Elm - Latest posts by @evancz Evan on Tue, 20 Jul 2021 11:54:34 GMT

The plan is to add an equatable constrained type var. I thought people knew this from the error:

Error: Trying to use `(==)` on functions.
There is no way to know if functions are "the same" in the Elm sense.
Read more about this at:
https://package.elm-lang.org/packages/elm/core/latest/Basics#==
which describes why it is this way and what the better version will look like.

Following that link gives the following message:

Note: Do not use (==) with functions, JSON values from elm/json , or regular expressions from elm/regex . It does not work. It will crash if possible. With JSON values, decode to Elm values before doing any equality checks!

Why is it like this? Equality in the Elm sense can be difficult or impossible to compute. Proving that functions are the same is undecidable, and JSON values can come in through ports and have functions, cycles, and new JS data types that interact weirdly with our equality implementation. In a future release, the compiler will detect when (==) is used with problematic types and provide a helpful error message at compile time. This will require some pretty serious infrastructure work, so the stopgap is to crash as quickly as possible.

I also mention this in the roadmap:

add a constrained type variable eq to get rid of the runtime error for (==) on functions

To give some extra context, the current behavior is under the theory that, in the absence of the compile-time check, it’s still best to fail as soon as possible. That way type error can be corrected. I think this is better than having behavior like “it’s always false” or “use reference equality” or “use syntactic equality” or whatever which would (1) prolong the life of such code, (2) still be extremely surprising to some large subset of people, and (3) make the eventual introduction of an equatable type even more disruptive.

I appreciate that not everyone agrees with this reasoning, but I hope this clears up that aspect of this discussion. I also appreciate that people in the conversation may not have seen the error message recently / may not remember the exact details of it, so no worries. I just want to add these details in!

Nonetheless, I’m sorry I did not mention that this was the plan in my initial comment. I thought the poster was just asking, “the current behavior/plan makes sense, but what if (==) could be defined on functions in a good way that would work as a long-term solution?” That is an interesting theoretical question.

In languages with dependent types like Coq, you can prove things quite like this! For example, I had a compilers course where we wrote a simple evaluate : AST -> Value function and then proved that it had the same behavior for all inputs as a compilation pipeline that introduced optimizations. That way you can have a proof that your compiler (and all of your optimizations) preserve the language semantics. These proofs cannot be inferred, and I personally found it extremely difficult to create the proofs myself, but it is still quite interesting to think about.

I thought the discussion was going to be mostly about that kind of thing.

Function equality

via Elm - Latest posts by @jfine2358 Jonathan Fine on Tue, 20 Jul 2021 11:11:20 GMT

An improved description of the existing behaviour of Elm would be a useful outcome of this discussion. This would help those who encounter problems with function equality.

I’d like this to state that function equality is an NP-complete problem, as in:

I feel that once the existing behaviour is better explained and understood, we’ll be better able to consider changes to Elm’s behaviour.

New release of elm-charts!

via Elm - Latest posts by @Sebastian Sebastian on Tue, 20 Jul 2021 01:41:23 GMT

Amazing work, thanks so much for doing this!

How disable comments make static analysis tools worse

via Elm - Latest posts by @system system on Mon, 19 Jul 2021 20:21:38 GMT

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.

Write CLI scripts in Elm (IO Monad)

via Elm - Latest posts by @edgerunner Mert Torun on Mon, 19 Jul 2021 19:29:43 GMT

I have been working on something that could use this. Currently I’m using ports and Platform.worker called from a NodeJS script.

🎙️ Elm Radio Episode 35 - elm-spa v6

via Elm - Latest posts by @dillonkearns Dillon Kearns on Mon, 19 Jul 2021 16:27:32 GMT

Hello folks, we’ve got a fun Elm Radio episode today with the one and only @RyanNHG.

We talk about the latest version of elm-spa, including authenticated pages and the updated file-based router. Hope you enjoy!

Function equality

via Elm - Latest posts by @MarkHamburg Mark Hamburg on Mon, 19 Jul 2021 15:03:39 GMT

I was ready to let this wind down having gotten early on Evan’s definitive view that he would prefer functions be declared equal if they computed the same thing which really is impossible to compute. I just think that then argues for a type system mechanism to prevent such equality checks from sneaking into the code.

But I stirred the hornet’s nest and it seems some of my explanations for why this might matter have lead to more confusion.

First, on crashes, I refer again to message 5 in this thread. Function equality check crashes in Elm fall into a category that is both potentially detectable at compile time (unlike stack overflow) but aren’t caught. They can’t be caught at module load time the way cyclic references are. Instead, you have to actually perform the comparison and not have it short-circuited by referential equality. The net result is that this is a path to what could have been preventable crashes in production. It also leads to incidents like the recent case of someone here being puzzled at why comparing HTTP requests could crash. To understand why, you have to know that Decoders are basically wrappers around functions.

Second, utility and performance. From a performance standpoint, lazy HTML demonstrates the value of caching. What if one wanted to build a caching mechanism for something else? For example layout computations that could not be handled by HTML or queries filtering down a dictionary full of items or subscription computations. But more broadly, the thing that characterizes functional programming languages is that they are much more friendly to building data structures that include functions as a first class component. See, for example, the discussion earlier in this thread about building dictionaries with the comparison function baked into the data structure. But if function equality checks can crash, then these need to be treated as second-class data structures ineligible for equality tests.

Finally, solutions. There seem to be three ways out if one doesn’t just accept the risks inherent in the current state of affairs. One is a type-system mechanism to prohibit function equality tests and hence equality tests of anything containing functions. One is to just use referential equality for functions. In practice, this will work but it does break some ability to reason about programs since it breaks referential transparency. And one is something like the structural equality definition I outlined which has the downside of being harder to compute with Elm’s current JavaScript implementation.

And with that summary, barring any significant new arguments — I really did find the point about >> semantics interesting to consider — I will now just tell myself that I’ve already pointed to all of the key issues.

New release of elm-charts!

via Elm - Latest posts by @joelq Joël Quenneville on Mon, 19 Jul 2021 14:24:58 GMT

I love this visual showcasing all the bar-chart terminology. :100: for friendly docs!

Function equality

via Elm - Latest posts by @lpil Louis Pilfold on Mon, 19 Jul 2021 12:28:43 GMT

I’ve spent some time reading the Elm generated JavaScript and I think in practice the behaviour isn’t surprising, so luckily this potential problem is easy to avoid.

Function equality

via Elm - Latest posts by @eike Eike Schulte on Mon, 19 Jul 2021 12:26:13 GMT

I think there is one place where function equality is commonly useful: Occasionally, one wants to create (or use) semi-generic data structures that require more information about the values of a given type than equality. For example, a Dict needs an order on the keys and a HashSet would need a hash function on the potential values. Now, Elm generates some instances of comparable, but custom types are left out. There is no hashable at all.

If one wants to use custom types in these data structures, there are the following options, none of which I find particularly good:

  • Replace a custom type that happens to be used as a key in a Dict by ints, strings and tuples of those two everywhere. This loses type safety in all other parts of the app.
  • Create a toKey function from your type to a type that can serve as a key, and insert this function whenever the type is used as a key. This is quite verbose and not in a way that increases code clarity, in my opinion.
  • Create a new module containing a copy of (parts of) Dict’s API, only with all the toKey calls already included. This is also busywork and it requires the reader of the code to keep an additional type in their head. Also, it increases the size of the compiled product.

A solution to this problem are AnyDict implementations that store the toKey function with the data structure (so you only need to supply it when creating a new instance, not on every operation). They currently work reasonably well: If you always supply the same global toKey function on instantiation, you can even compare them for equality, as references to the exact same function can be compared for equality and are considered equal. If you mess up and supply different functions, you run into a runtime error. (But in particular, always using a top-level toKey is a good heuristic to ensure that only one copy of the function exists.)

If other goal is to remove the runtime error, there should be a solution to the generic data structure problem of some form. Replacing the runtime error by False would do that, though I’m not convinced that replacing errors by default values is not more dangerous than the error (you might corrupt data because you work under false assumptions). Introducing an equatable constraint to exclude function from == altogether does not. Making more types comparable in exchange would help with the case of Dict but not with other situations (e.g., a potential HashSet).

New release of elm-charts!

via Elm - Latest posts by @lydell Simon Lydell on Mon, 19 Jul 2021 12:18:10 GMT

Maybe! The current line height works, though I spontaneously thought it might look a little bit cramped. I inspected VSCode and some sites with code blocks (in documentation), and the line height seems to be commonly closer to 1.5.

New release of elm-charts!

via Elm - Latest posts by @terezka Tereza Sokol on Mon, 19 Jul 2021 12:09:46 GMT

Thank you for the feedback! I think I fix both issues now. Do you think the line height should still be larger?

New release of elm-charts!

via Elm - Latest posts by @lydell Simon Lydell on Mon, 19 Jul 2021 11:52:22 GMT

What a beautiful page! Two small details about it: The code blocks have overflow-x: scroll instead of overflow-x: auto, so I get an unnecessary scrollbar most of the time:

Also, the code blocks seem to have very small line height – for example, you can see how , and ] below bump into each other.

Note that on a Mac, you need to connect an external mouse or set General > Show scroll bars: always to see the unnecessary scroll bars (Windows and Linux users see it out of the box):

New release of elm-charts!

via Elm - Latest posts by @rasputin303 Ed Kelly on Mon, 19 Jul 2021 10:40:47 GMT

Amazing, thank you! The site is beautiful and the API looks really good, I will enjoy exploring this!

New release of elm-charts!

via Elm - Latest posts by @terezka Tereza Sokol on Mon, 19 Jul 2021 10:36:29 GMT

Hi everyone,

I released a new version of elm-charts today! Features include:

  • :wave: Great support for interactivity
  • 👯‍♀️ Mixed chart types
  • :heavy_heart_exclamation: Easily add irregular details
  • :framed_picture: Tons of examples

Check it out at elm-charts.org!

Thanks to everyone who gave me feedback on the library :heart:

Function equality

via Elm - Latest posts by @georgesboris on Mon, 19 Jul 2021 09:15:29 GMT

The thing that makes me more scared about the function equality strategy is that, unlike JS – where I’m the metal defining functions myself and I know they have the references I expect – when I’m in Elm I have no idea how my definitions (lazy? auto-curried?) will turn into actual javascript functions, if there will be some optimizations that makes my superficial understanding different from what is actually happening under the hood.

This would create the problem of a “lack of runtime expections” but for the wrong reasons since things would be working in a possibly buggy behavior without the possibility of realising it.

Maybe this is just my lack of understanding about how it works tho.

Elm-book – books with markdown and embedded elm components

via Elm - Latest posts by @georgesboris on Mon, 19 Jul 2021 09:07:26 GMT

I thought about that! It was mainly two things (tho I know there is the downside of decreased type-safety when using some random custom element and random custom props):

  • since I’m not only focusing on storybook-like documents, it would be great to be able to use elm components wherever I want in the markdown. Including in the middle of other tags (using the “displayInline” option) - this is trivial when using dillonkearns/elm-markdown. when I first explored the idea you mentioned it seemed trickier but thinking about it now it is less tricky and it opens up a few possibilities (based on other recent feedbacks…) - I’ll keep exploring it :grin:

  • working with markdown and elm is a bit of a painful experience. there is no syntax highlighting. no autoformat or anything. so I thought that separating both steps would enable code generation more easily since you can split the writing of markdown somewhere else and then just replace the string on the elm file… even on the markdown-in-elm approach I found it simple to just move components around without thinking about the boundaries between text and components.

but its definitely an interesting idea! thanks for bringing it in. I’m putting a pile of feedback together for future work. thanks!

 newer latest older