Lisplog

Blogging in Lisp

Search

Feed Aggregator

Rendered on Thu, 18 Oct 2018 06:32:24 GMT  newer latest older 
Next udpate: Thu, 18 Oct 2018 07:00:00 GMT feeds

Elm-conf videos are published!

via Elm Discourse - Latest posts by @ggerico germain delpy on Thu, 18 Oct 2018 05:04:09 GMT

There is another interesting (I would say more challenging) talk of Sam Rowe called “Complex Animations Done Well” which tries to introduce complexity into the elm architecture, i.e. multiple states management: true state, current visual state, target visual state instead of just one single state.

This is promising and I wish the community will one day tackle these problems and succeed. Kind of vuejs philosophy to fit small AND big (= complex) projects ( The Progressive JavaScript Framework ).

If you are reading Sam:
Could you make a repo on your github demonstrating the spring and exit animation examples using this states management?
Do you plan to publish a package?

Expect.equal argument order convention

via Elm Discourse - Latest posts by @rtfeldman Richard Feldman on Thu, 18 Oct 2018 03:43:05 GMT

To clarify, the code was demonstrating “what if there was a bug in the implementation of (*), which the test revealed” (in this case, the bug would be "(*) squares its second argument before performing the multiplication")

If Expect.equal takes an { expected : Expectation, actual : Expectation } record, then it can’t accept something different for fuzz than it does in the case of test - that’s just the argument it accepts everywhere!

An alternative would be to have Expect.equal for test and some other function (maybe Expect.same) that’s tailored to fuzz, and then tell everyone to use the one for the one and the other for the other, but honestly that sounds too clunky to consider seriously.

Anyway, I’m gonna duck out of this discussion. Like I said, I don’t think expected/actual is worth further exploration. :slightly_smiling_face:

Beginner looking for help refactoring game event callbacks

via Elm Discourse - Latest posts by @system system on Thu, 18 Oct 2018 02:45:05 GMT

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

Consequences of functions in the model with 0.19?

via Elm Discourse - Latest posts by @dmy on Thu, 18 Oct 2018 02:28:41 GMT

Hi,

I was looking at rtfeldman/elm-sorter-experiment and its Sorter.Dict implementation and noticed that it stores the Sorter function in the type.

It seems to be also the case for all Dict implementations that support any key type (all the ones I looked at use a k -> comparable function argument for Dict.empty), for example elm-dictset or any-dict.

A known rule of The Elm Architecture is to never put functions in your Model or Msg types, so I wonder what are the exact impacts in 0.19 to do so.

I guess it would break the debugger serialization and therefore import/export/time travel, but I would like to know if there are other consequences like those discussed in 0.17 concerning equality tests?
Could this break Html.Lazy? Could this break dicts comparisons?

Finally, have some of you doing it regretted it for some reasons?

There was a related discussion a few months ago concerning functions in messages but I don’t think that this gives all the answers:

Thank you

Handling dependent multiple Http requests with a bad api structure

via Elm Discourse - Latest posts by @kuroski Daniel Kuroski on Thu, 18 Oct 2018 01:59:57 GMT

Hello guys :wave:

I am currently studying elm and I came across an interesting problem…
I’m creating a pokedex using the pokeapi
The fact is that the api modeling is very verbose and complex

The scenario I want is the following:

  • Search a pokemon by its name
  • Then list its information (name, picture, description)
  • And list its evolutions

The cenario is:

  • First I have to fetch the pokemon
  • Then with the response, I must get its specie (this is another request) and I get the url by accessing this property pokemon.species.url
  • Then I must request:
    • /api/v2/pokemon-species/4/ (charmander specie page)
  • THEN I must request its evolution chain to get all charmander evolutions and so on…

I currently came up with the below solution and I would like to know if there is a better way to do this.

I want you to focus on the request line in SearchPokemon update

-- Api module

pokeDecoder : Decoder Pokemon
pokeDecoder =
    Decode.succeed Pokemon
        |> required "name" string
        |> requiredAt [ "species", "url" ] string

specieDecoder : Decoder Specie
specieDecoder =
    Decode.succeed Specie
        |> requiredAt [ "genera", "2", "genus" ] string
        |> requiredAt [ "evolution_chain", "url" ] string

getPokemon : String -> Task Http.Error Pokemon
getPokemon term =
    let
        url =
            "https://pokeapi.co/api/v2/pokemon/" ++ term ++ "/"
    in
    Http.get url pokeDecoder
        |> Http.toTask



getSpecie : Pokemon -> Task Http.Error Specie
getSpecie pokemon =
    Http.get pokemon.specieUrl specieDecoder
        |> Http.toTask

-- Update module

type Msg
    = SearchPokemon
    | PokeSpecieResponse (Result Http.Error ( Pokemon, Specie ))

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        SearchPokemon ->
            let
                request =
                    getPokemon (String.toLower model.searchInput)
            in
            ( { model | loading = True }
            -- Here is the tricky part
            , request
                |> Task.andThen
                    (\pokemon ->
                        Task.map (\specie -> ( pokemon, specie )) (getSpecie pokemon)
                    )
                |> Task.attempt PokeSpecieResponse
            )

        PokeSpecieResponse (Ok ( pokemon, specie )) ->
            ( { model
                | loading = False
                , pokemon = Just pokemon
                , specie = Just specie
              }
            , Cmd.none
            )

        PokeSpecieResponse (Err error) ->
            ( { model | loading = False, pokemon = Nothing }, Cmd.none )

I’m omitting some of the complexity, but if for example I want to also search the evolutions, the request is gonna grow by something like this:

request
    |> Task.andThen
        (\pokemon ->
            Task.map (\specie -> ( pokemon, specie )) (getSpecie pokemon)
        )
    |> Task.andThen
        (\( pokemon, specie ) ->
            Task.map (\evolution -> ( pokemon, specie, evolution )) (getEvolutionChain specie)
        )
    |> Task.attempt PokeSpecieResponse

My problem is:

  • I need to request pokemon, species and evolutions
  • So it’s 3 requests that are dependent, if one fail I want the whole process to fail
  • Every task chain, I must keep the latest request result value
  • So at the end I pass a command to update the model

This code works, but for me to delve into the evolutions this gets even more compelling, since pokeapi returns a grotesque json and I would have to deal, and this code tends to be a mess.

And that’s it >_<, I’m doing this for fun, but this case may appear in the real world

Thaaanks a lot for your attention =D

Elm-units 1.0: Units handling for Elm

via Elm Discourse - Latest posts by @system system on Wed, 17 Oct 2018 21:43:32 GMT

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

Elm reactor - init with flags for 0.19

via Elm Discourse - Latest posts by @dmy on Wed, 17 Oct 2018 20:29:43 GMT

I’m not sure though why you call it outputtoignore, so let me try to explain elm-live behavior in more details to be clear.

AFAIK, when connecting to localhost:8000 (by default), elm-live will always serve index.html. If you specify a path in the url, it will serve the corresponding file or 404 if not found (unless you use --pushstate in which case it will always serve index.html

elm-live performs exactly like elm make:

1. Let “elm make” generate index.html

If you don’t need any additional javascript (like flags, ports, custom elements or observers), you can let elm make generate the html file:

$ elm-live src/Main.elm

index.html will be generated by elm make in . and init the elm application.

2. Tell elm make to generate a js file and use your own index.html

If you need your own index.html file (to add some flags or some javascript), then use elm make --output to generate a javascript file without the html:

$ elm-live src/Main.elm -- --output=elm.js

Every option after the -- is passed to elm make. (you can call elm.js main.js instead or whatever name, given that you use it correctly in index.html).

It is then your responsibility to initialize elm in the index.html file that will be served.

However as you noticed, if you put your own index.html in . and forgot the --output=elm.js, this will generate ./index.html and overwrite your own. But this is not elm-live that overwrites your index.html, this is elm make. You can test exactly the same behavior by using only elm make.

This is why I advise to put your own index.html in a subdirectory and use elm-live -d to serve files from it (again always index.html by default without a specific url).

As a bonus, all your static files (index.html, css, js, images) and the generated elm.js will be cleanly grouped in a subdirectory that you can serve directly when deploying on github pages or netlify for example (preferably after minification).

Handling bounds errors safely whilst keeping a relaxed type

via Elm Discourse - Latest posts by @rupert Rupert Smith on Wed, 17 Oct 2018 20:12:17 GMT

This gives me an idea of a function that could be added to elm-community/dict-extra and array-extra if there was one:

swap : Int -> Int -> Array a -> Array a
swap : comparable -> comparable -> Dict comparable v -> Dict comparable v

The contract would be, the functions swaps the data values located by the keys, if the keys are both valid, otherwise it just returns the data structure unchanged. There may be other dict-like data structures where swap operations are handy.

Elm reactor - init with flags for 0.19

via Elm Discourse - Latest posts by @Viir Michael Rätzel on Wed, 17 Oct 2018 19:25:21 GMT

Testing this, I have renamed the Elm entry file to Main.elm, and used this commandline:
elm-live Main.elm -- --output=elm.js
With this setup, elm-live responds with a 404 Not Found with a the following body:

File Not Found

I see that the elm.js file was created tough.

Expect.equal argument order convention

via Elm Discourse - Latest posts by @andys8 Andy on Wed, 17 Oct 2018 19:24:59 GMT

Interesting! I’m not getting the example, because the code snippet wouldn’t generate 4 and 2, but 2 and 2. But I think I got the point. Property based tests could be different compared to “classic” unit tests with static values for expected. I’d think about if my expectation in a fuzz test is instead, that the property num1 * num2 == num2 * num1 is True. And my test error could be: "Your property num1 * num2 == num2 * num1 won’t hold for input (1,2). Although this is perhaps over specific for this example.

Type Aliases: Not useful?

via Elm Discourse - Latest posts by @joelq Joël Quenneville on Wed, 17 Oct 2018 19:23:53 GMT

I’m a huge fan of custom types! :heart_eyes:

In my own code, I follow a similar system as @brian. Here are some stats from a recent small SPA project I worked on: (~3000 line of Elm code):

There are 30 uses of type alias (vs 23 uses of type). Of those 30 aliases:

  • 26 are records
  • 2 are aliasing model to another type to reduce churn in boilerplate functions
  • 1 is a function
  • 1 is a complex dictionary type with both variables filled in.

In this codebase, type aliases are not used for safety. They aren’t primarily used to improve readability.

  1. Their main use is shortening long complex types to a short one or two word name that can more easily be used in signatures.
  2. It’s also a form of DRY. If I change the type of a record or a dictionary, I only need to update the type in a single place.

Better readability is a nice side-effect of both goals mentioned above :slightly_smiling_face:


An exception to that general rule is that I'm aliasing my top-level `Model` type:
type alias Model = Result String SomethingElse

This is so the standard signatures of update, main, view, and init can remain the same, even as my model type evolves over time.

Parsing column-based data with elm/parser

via Elm Discourse - Latest posts by @Libbum on Wed, 17 Oct 2018 19:17:33 GMT

Oh, well you can easily just use Parser.Advanced.problem instead of Parser.problem. Then set your own error type - directly employing ExpectingFloat for example.

Parsing column-based data with elm/parser

via Elm Discourse - Latest posts by @ChrisWellsWood Chris Wells Wood on Wed, 17 Oct 2018 19:01:32 GMT

The reason it seems a bit jarring is that as soon as you drop out of Parser.elm you lose the rich error information generated by the parser.

Type Aliases: Not useful?

via Elm Discourse - Latest posts by @brian Brian on Wed, 17 Oct 2018 18:02:12 GMT

I think there are two competing concerns going on here:

  1. booleans are inherently unclear
  2. type aliases are sometimes unclear

For the boolean stuff, yeah: use a custom type. I’m on board with that every time. You will almost always get a clearer, safer API. Here’s a whole talk on that: Solving the Boolean Identity Crisis by Jeremy Fairbank.

As for type aliases in general, here are my rules:

  • never use type aliases for simple types like Int or Bool. They let you express intent but, crucially, are not checked by the compiler (e.g. RoundUp and RoundToTens in your example can be exchanged and will still compile.)
  • sometimes use type aliases for types with type parameters so that Result x a or Dict comparable a become HttpResponse or Students. These have a very low chance of being accidentally swapped in, and the damage is pretty low if they are. That said, I always start with a closed custom type and open it up if necessary instead of the other way around, and has no runtime cost as the compiler will unbox them if it can.
  • always use type aliases for records. That’s it.

Optimize elm compilation with webpack

via Elm Discourse - Latest posts by @opvasger Asger Nielsen on Wed, 17 Oct 2018 16:25:00 GMT

You can now use elm-minify as part of Webpack with this plugin.

An example can be found here.

Let me know if you have any problems with the package :sunny:

Parsing column-based data with elm/parser

via Elm Discourse - Latest posts by @Libbum on Wed, 17 Oct 2018 16:15:44 GMT

As an aside, if you take a look at the way Tereza is building the YAML parser:

Here is the union type for the model which includes strings and floats, and the fromString function does effectively the same thing as above.

Then, that function maps incoming data from a getChompedString pipe.

So there’s at least one other use of this pattern in the wild.

 newer latest older