For the http request functions, both the Elm tutorial and the docs suggest passing a constructor function (e.g. GotText
) to an expect function (e.g. expectString
), for the expect
field, e.g:
type Msg
= GotText (Result Http.Error String)
getPublicOpinion : Cmd Msg
getPublicOpinion =
Http.get
{ url = "https://elm-lang.org/assets/public-opinion.txt"
, expect = Http.expectString GotText
}
I understand this, but it seems to me that constraining the API to require a constructor function (e.g. GotText
) is overly restrictive.
For example, it is possible to use identity
to extract the constructor function GotText
from the request function get
:
getPublicOpinion = Cmd.map GotText (
Http.get
{ url = "https://elm-lang.org/assets/public-opinion.txt"
, expect = Http.expectString identity
})
But that begs the question: Why does the http API require the constructor function at all*?
* Or at least allow us to omit the expect
field and return Result Http.Error String
.
This isn't a restriction, it's actually a convenience.
If Http.expectString
didn't take a function (Result Http.Error String -> msg)
then Http.get
would return a Cmd (Result Http.Error String)
which is what it does if you pass in identity
.
Since the result of all Cmd
s always needs to be a Msg
that the runtime can pass in to your update
function you would always have to Cmd.map
the result of every call Http.get
to convert the Cmd (Result Http.Error String)
to a Cmd Msg
.
To avoid having to call Cmd.map
every time you call Http.get
the API allows you to pass the function that will do the conversion straight to Http.expectString
. This is less typing, involves less nesting so it's clearer to the reader.
You'll see this convention repeated across lots of modules. eg.:
Json.Encode.list
has the type list : (a -> Value) -> List a -> Value
it takes a function to do the JSON encoding of the elements of the list, this saves you from having to use List.map
to JSON encode the element of the list first.
Html.Events.onInput
has the type onInput : (String -> msg) -> Attribute msg
it takes a function to convert the String
to a msg
value, this saves you from having to Html.Attribute.map
the result of onInput
to convert the Attribute String
to a Attribute msg
. This would be a really pain if you had to call Html.Attribute.map
for every event handler and Attribute
on any Html elements.