Reputation: 77
I'm trying to understand how Elm type system works. Coming from an imperative programming background, i'm used to take advantage of a debbuger with step and breakpoints to figure out what's happening. But apparently that is not the functionnal way.
Using the REPL to figure out trivial exemples is easy, but it gets way more complicated with something like Http.get for exemple.
Here is what i have tried :
Apparently I have to define a certain custom type for the message to be returned by the runtime when the HTTP request has been done :
> type Message = Done (Result Http.Error String)
Now I'm storing the result of the Http.get in some variable :
> test = Http.get { url = "http://192.168.1.10:3000/site", expect = Http.expectString Done }
Then i'd like to see what's inside test
:
> test
<internals> : Cmd Message
If i understood correctly, test
seems to have the expected type and is now some command i can somehow send to the Elm runtime.
Now here is what i want to do :
1 - print what's inside the Message
payload of my test
command.
2 - send the command to the runtime and fetch the result somehow (from the REPL)
3 - print what's inside the Message
i'm supposed to get back from the runtime.
Is it possible ? Does it make sense ? If not, how am I supposed to take a look at whats happening behind the apparent magic in order to really understand Elm, especially the rather cryptic type annotations ?
Bonus question :
Http.get
has the following definition :
get :
{ url : String
, expect : Expect msg
}
-> Cmd msg
Do msg
have to be a custom type ?
Upvotes: 0
Views: 199
Reputation: 40533
Do
msg
have to be a custom type ?
No. It can be any type, so for instance that could just as well be String
for instance.
Now to the meat of the question: In the REPL, you can evaluate Elm expressions - and Elm as such is a pure language, which means it cannot execute (almost) any effects, such as HTTP requests.
However, there is a special kind of value in Elm called a Cmd
, that if handed over to the Program
value will ask the runtime to execute some effect on your behalf. For this to work, you must designate that Program
value your application entry point by naming it main
.
This cannot be done in the REPL; hence the Elm REPL cannot execute Cmd
s.
So in order to play with Cmd
, you'll need to create an Elm application and run it in the browser.
Something like this:
import Browser
import Html
main = Browser.element
{ init = \() -> ({}, test) -- ask the runtime for your message
, update = update
, subscriptions = \_ -> Sub.none
, view = \_ -> Html.text "Hello world!"
}
update msg model =
case msg of
Done result ->
let
_ = Debug.log "HTTP request completed" result
in
( model, Cmd.none )
1 - print what's inside the Message payload of my test command.
Your test
command has no Message payload to print. The type parameter Cmd Message
doesn't mean that the value somehow "contains" the Message
type, it just asserts a certain kind of relationship between the types. In this case a future relationship, which you can think of as a "Command that in the future may produce a Message
type of value".
You could think of the Cmd
type implemented something like this (it's not, but could be):
type Cmd msg
= NoCmd
| HTTP Method Url (Response -> msg)
| Sleep Duration (() -> msg)
...
Upvotes: 4