Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elm: How to define a function that performs a request with message as parameter

Tags:

elm

In Elm 0.18, how can I define a function that performs a request, which takes as parameter the message for the update function when receiving the response?

The following code:

mypost : String -> String -> msg -> Cmd msg
mypost url csrf mymsg =
    Http.request
        { method = "POST"
        , headers = [ Http.header "X-CSRFToken" csrf ]
        , url = url
        , body = Http.emptyBody
        , expect = Http.expectJson mydecoder
        , timeout = Nothing
        , withCredentials = False
        }
        |> RemoteData.sendRequest
        |> Cmd.map mymsg

doesn't compile:

The argument to function map is causing a mismatch.

124| Cmd.map m ^ Function map is expecting the argument to be:

a -> msg

But it is:

msg

Hint: It looks like a function needs 1 more argument.

And what if the msg takes a parameter? for example:

|> Cmd.map (mymsg myParamTomymsg)

This has led me to having lot's of code duplication, there must be a better way...

like image 841
Francisco Dibar Avatar asked Aug 26 '17 16:08

Francisco Dibar


1 Answers

This answer is written assuming you're using the standard Http package. If you're new to Elm, I'd recommend to play around with it first and the use open source packages.

TL;DR

The type of mymsg in your code is supposed to be a -> msg, where type variable a is the same type as the value produced by a decoder mydecoder

mypost : String -> String -> (a -> msg) -> Cmd msg

You have to specify the type explicitly and replace a with the type of response.

Longer explanation

In other words, you have to explicitly say that the first argument passed to Http.send is a function, that maps a response to a message.

When you define a Union Type, the Msg is the name of your new type and NoOp with Update are the actual values which can act as constructors of values of Msg type.

type Msg
    = NoOp
    | Update String

By using Update "Hello" in the code we create a value of Msg type, where a string "Hello" is tagged with a tag Update The same thing happens in Http.send, except that the type of tagged value is expected to be a Result.

The type of Update is implied to be String -> Msg

Let's have a look at the type annotation definition for Http.send:

send : (Result Error a -> msg) -> Request a -> Cmd msg

Here's an example of a generic GET request:

get : Int -> Difficulty -> (Result Error TriviaResult -> msg) -> Cmd msg
get amount difficulty msg =
    Http.get (triviaRequestUrl amount difficulty) decoder
        |> Http.send msg

If you're using remotedata

You have to fix your type definition annotation:

myget1 : (WebData HttpBin -> msg) -> Cmd msg

I hope this helps.

like image 73
halfzebra Avatar answered Oct 18 '22 23:10

halfzebra