GET / HTTP/1.1<html>
<head>...</head>
<body>
<h1>Wonderfull site!</h1>
<p>Hello</p>
</body>
</html>GET / HTTP/1.1<html>
<head>...</head>
<body>
<h1>Wonderfull site!</h1>
<p>Hello</p>
</body>
</html>GET /users/ HTTP/1.1<html>
<head>...</head>
<body>
<h1>Wonderfull site!</h1>
<ul>
<li>Arthur</li>
<li>Ford</li>
</ul>
</body>
</html>GET /userlist/ HTTP/1.1
Accept: application/jsonHTTP/1.1 200 OK
Content-Length: 130
[ { "name": "Marvin",
"kind": "Robot" },
{ "name": "Zaphod",
"kind": "ET"},
{ "name": "Arthur",
"kind": "human"}
]GET /userlist/ HTTP/1.1
Accept: application/jsonHTTP/1.1 200 OK
Content-Length: 130
[ { "name": "Marvin",
"kind": "Robot" },
{ "name": "Zaphod",
"kind": "ET"},
{ "name": "Arthur",
"kind": "human"}
]Display those data with JS (via Elm).
"AJAX"
GET /userlist/ HTTP/1.1
Accept: application/jsonA
B
C
D
E
F
G
H
I
Only data, not tied to JavaScript
15
15.2
-54
5e10""
"Hello world"
"😊"15
15.2
-54
5e1015
15.2
-54
5e10true
false""
"Hello world"
"😊"15
15.2
-54
5e10""
"Hello world"
"😊"true
falsenull[5, 42, "hello", null][5, 42, "hello", null]{ "name": "Arthur",
"kind": "human"
}
[5, 42, "hello", null]
[ { "name": "Marvin",
"kind": "Robot" },
{ "name": "Zaphod",
"kind": "ET"},
{ "name": "Arthur",
"kind": "human"}
]{ "name": "Arthur",
"kind": "human"
}
{ "server": "Heart-of-gold",
"arenas": [
{ "game": "pong",
"players": [
{ "name": "Arthur",
"score": 5 },
{ "name": "Zaphod",
"score": 2 }
]
}
]
} getDay : Int -> Maybe String
getDay dayNumber = case dayNumber of
0 -> Just "Monday"
1 -> Just "Tuesday"
...
6 -> Just "Sunday"
_ -> Nothing
res : Int
res = case (String.toInt "42") of
Just x ->
2 * x
Nothing ->
0
type Result error value
= Err error
| Ok valuetype Result error value
= Err error
| Ok valueCan be any type
type Result error value
= Err error
| Ok valuetype Maybe a
= Nothing
| Just atype Result error value
= Err error
| Ok valuetype Maybe a
= Nothing
| Just atype Result error value
= Err error
| Ok value
toBool : String -> Result String Bool
toBool s = case s of
"true" -> Ok True
"false" -> Ok False
"42" -> Err "Nice try!"
_ -> Err ("not a bool: " ++ s)type Result error value
= Err error
| Ok value
toBool : String -> Result String Bool
toBool s = case s of
"true" -> Ok True
"false" -> Ok False
"42" -> Err "Nice try!"
_ -> Err ("not a bool: " ++ s)Error messages,
impossible with Maybe
type Result error value
= Err error
| Ok value
toBool : String -> Result String Bool
toBool s = case s of
"true" -> Ok True
"false" -> Ok False
"42" -> Err "Nice try!"
_ -> Err ("not a bool: " ++ s)type Result error value
= Err error
| Ok value
toBool : String -> Result String Bool
toBool s = case s of
"true" -> Ok True
"false" -> Ok False
"42" -> Err "Nice try!"
_ -> Err ("not a bool: " ++ s)kineticE : Float -> Float -> Result String Float
kineticE mass speed =
...
import Json.Decode as Decode exposing (int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
Decode.decodeString :
Decoder val
-> String
-> Result Error valDecode.decodeString :
Decoder val
-> String
-> Result Error valimport Json.Decode as Decode exposing (int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
Decode.decodeString :
Decoder val
-> String
-> Result Error valThe type we want to decode to
import Json.Decode as Decode exposing (int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
Decode.decodeString :
Decoder val
-> String
-> Result Error valThe decoder, describing how to transform a JSON value into
an Elm value of type "val"
import Json.Decode as Decode exposing (int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
Decode.decodeString :
Decoder val
-> String
-> Result Error valThe JSON we want to decode:
import Json.Decode as Decode exposing (int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
Decode.decodeString :
Decoder val
-> String
-> Result Error valEither:
import Json.Decode as Decode exposing (int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
import Json.Decode as Decode exposing (Decoder, int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
int : Decoder Int
Decode.decodeString :
Decoder val
-> String
-> Result Error valimport Json.Decode as Decode exposing (Decoder, int)
Decode.decodeString int "4" == Ok 4
Decode.decodeString int "hello" == Err ...
Decode.decodeString int "1 + 2" == Err ...
int : Decoder Int
Decode.decodeString :
Decoder Int
-> String
-> Result Error Intimport Json.Decode as Decode exposing
(Decoder, decodeString)
Decode.int : Decoder Int
decodeString Decode.int "4" == Ok 4
Decode.string : Decoder String
decodeString Decode.string "\"hey\"" == Ok "hey"
decodeString Decode.string "3.14" == Err ...
decodeString Decode.string "{ \"hello\": 42 }" == Err ...
Decode.bool : Decoder Bool
decodeString bool "true" == Ok True
decodeString bool "42" == Err ...import Json.Decode as Decode exposing
(Decoder, decodeString, list, int, bool)
Decode.list : Decoder a -> Decoder (List a)
decodeString (list int) "[1,2,3]" == Ok [1,2,3]
decodeString (list bool) "[true,false]" == Ok [True,False]
decodeString (list int) "[true,false]" == Err ...
decodeString (list bool) "[1,2,3]" == Err ...
decodeString (list int) "42" == Err ...42Starting point :
https://ellie-app.com/6H9QpXpnJXka1
[42, 10, 52]Starting point :
https://ellie-app.com/6H9Ry2yg45Wa1
[[1, 2, 3], [42, 6, 9], [5,1]]Starting point :
https://ellie-app.com/6H9PfrTdj3ka1
import Json.Decode as Decode exposing
(Decoder, decodeString, field, int, string)
json = "{ \"username\": \"Tom\", \"age\": 42 }"
Decode.field : String -> Decoder a -> Decoder a
decodeString (field "username" string) json == Ok "Tom"
decodeString (field "age" int) json == Ok 42
decodeString (field "age" string) json == Err ...
decodeString (field "username" int) json == Err ...
{ "name": "Ford", "score": 42 }Starting point :
https://ellie-app.com/6KKSDtSCM6Ma1
import Json.Decode as Decode exposing
(Decoder, decodeString, field, int, string, map2)
json = "{ \"username\": \"Tom\", \"age\": 42 }"
type alias User = { name : String, age : Int }
userDecoder : Decoder User
userDecoder =
map2 User
(field "username" string)
(field "age" int)
decodeString userDecoder json
== Ok { name = "Tom", age = 42 }
import Json.Decode as Decode exposing
(Decoder, decodeString, field, int, string, map2)
json = "{ \"username\": \"Tom\", \"age\": 42 }"
type alias User = { name : String, age : Int }
userDecoder : Decoder User
userDecoder =
map2 User
(field "username" string)
(field "age" int)
decodeString userDecoder json
== Ok { name = "Tom", age = 42 }
Order of the fields matters!
import Json.Decode as Decode
Decode.decodeString userDecoder
"""{ "username": "Tom", "age": 42, "city": "NY" }"""
type alias User =
{ name : String
, age : Int
}
userDecoder: Decoder User-- produces:
Ok { name : "Tom", age : 42 }import Json.Decode as Decode
Decode.decodeString userDecoder
"""{ "username": "Tom", "age": 42, "city": "NY" }"""
Decode.decodeString userDecoder
"""{ "username": "Tom", "nbYears": 42, "city": "NY" }"""-- produces:
Ok { name : "Tom", age : 42 }-- produces:
Err ...{
"name": "Ford",
"score": 42,
"favorite_color": "red",
"from": "Betelgeuse"
}Starting point :
type alias Player =
{ name : String
, score: Int
, origin: String
}{
"players": [{
"name": "Ford",
"score": 42,
"favorite_color": "red",
"from": "Betelgeuse"
}],
"games": ["pong", "tetris"]
}Starting point :
type alias Board =
{ players: List Player
, games : List String
}
-- Player is the same
-- as previouslyinitialModel : Model
initialModel =
{ count = 0 }
update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
{ model | count = model.count + 1 }
view : Model -> Html Msg
view model =
div []
[ button [ onClick Increment ] [ text "+1" ]
, text <| String.fromInt model.count
]init : Model
view : Model -> Html Msg
update : Msg -> Model -> ModelGET /userlist/ HTTP/1.1
Accept: application/jsonHTTP/1.1 200 OK
Content-Length: 130
[ { "name": "Marvin",
"kind": "Robot" },
{ "name": "Zaphod",
"kind": "ET"},
{ "name": "Arthur",
"kind": "human"}
]init : Model
view : Model -> Html Msg
update : Msg -> Model -> Modelinit : flags -> (Model, Cmd Msg)
view : Model -> Html Msg
update : Msg -> Model -> (Model, Cmd Msg)1. Hey Runtime,
please perform an HTTP request!
3. Ok, here is the response
2.
1. A new model indicating "Loading"
4. A new model with loaded data
type Result error value
= Err error
| Ok value
-- in the module Http
type Error
= BadUrl String
| Timeout
| NetworkError
| BadStatus Int
| BadBody StringshowResp : Result Http.Error (List User)
-> String
showResp resp =
case resp of
Ok users ->
showUsers users
Err _ ->
"An error occured, I'm sory!"
showResp : Result Http.Error (List User)
-> String
showResp resp =
case resp of
Ok users ->
showUsers users
Err _ ->
"An error occured, I'm sory!"
showResp : Result Http.Error (List User)
-> String
showResp resp =
case resp of
Ok users ->
showUsers users
Err _ ->
"An error occured, I'm sory!"
The lazy way...
showResp : Result Http.Error (List User)
-> String
showResp resp =
case resp of
Ok users ->
showUsers users
Err Http.NetworkError ->
"You seem disconnected."
Err Http.Timeout ->
"The server is too slow."
Err _ ->
"An error occured, I'm sory!"
GET /userlist/ HTTP/1.1
Accept: application/jsonHTTP/1.1 200 OK
Content-Length: 130
[ { "name": "Marvin",
"kind": "Robot" },
{ "name": "Zaphod",
"kind": "ET"},
{ "name": "Arthur",
"kind": "human"}
]type Msg
= LoadUserClicked
| GotUsers (Result Http.Error (List User))<<Hey Runtime! Fetch data from "/userlist/" and
when you are done, issue a 'GotUsers'
message with the result and convert the data
with 'usersDecoder'!>>type Msg
= LoadUserClicked
| GotUsers (Result Http.Error (List User))Cmd Msg
<<Hey Runtime! Fetch data from "/userlist/" and
when you are done, issue a 'GotUsers'
message with the result and convert the data
with 'usersDecoder'!>>type Msg
= LoadUserClicked
| GotUsers (Result Http.Error (List User))Cmd Msg
Msg
Json decoder
<<Hey Runtime! Fetch data from "/userlist/" and
when you are done, issue a 'GotUsers'
message with the result and convert the data
with 'usersDecoder'!>>type Msg
= LoadUserClicked
| GotUsers (Result Http.Error (List User))init : flags -> (Model, Cmd Msg)
view : Model -> Html Msg
update : Msg -> Model -> (Model, Cmd Msg)Cmd Msg
Msg
Http.get { url = "/userlist/"
, expect = Http.expectJson
GotUsers
usersDecoder
}Json decoder
type Msg
= LoadUserClicked
| GotUsers (Result Http.Error (List User))type Msg
= GotUsers (Result Http.Error (List User))
| LoadUserClicked
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
LoadUserClicked ->
( model -- model not changed
, Http.get
{ url = "/userlist/"
, expect = Http.expectJson GotUsers usersDecoder
}
)
GotUsers result ->
( { model | users = result }
, Cmd.none -- no command to perform!
)