Sébastien BESNIER
initialModel =
{ count = 0 }
type Msg
= Increment
| Decrement
update msg model =
case msg of
Increment ->
{ model | count = model.count + 1 }
Decrement ->
{ model | count = model.count - 1 }
view model =
div [style "font-size" "200%"]
[ button [ onClick Increment ] [ text "+1" ]
, div [ style "color" "red" ] [ text <| String.fromInt model.count ]
, button [ onClick Decrement ] [ text "-1" ]
]
https://ellie-app.com/fDyHsFVJCska1
Challenge: Reset to 0
No mutation! Only values and pure functions
No mutation! Only values and pure functions
Do you know impure functions?
See Elm architecture:
eight = 5 + 3
eight = round 8.3
add a b = a + b
add a b = a + b
-- call that function:
eight = add 7 1
Compute length of \(\texttt{"hello world"}\) and add 5 to it using the \(\texttt{add}\) function (in 1 expresion!)
String.length "abc" -- returns 3
eight = add 7 1
add a b = a + b
add : Int -> Int -> Int
add a b = a + b
String.length : ???
String.length : String -> Int
add3 a b c = a + b + c
add3:
Int
-> Int
-> Int
-> Int
add3 a b c = a + b + c
String.append "hello " "world"
-- returns "hello world"
String.append "hello " "world"
-- returns "hello world"
String.append : String -> String -> String
t = add 5 String.append "hey" "hoy"
f a b =
String.length (String.append a b)
g a b =
add (String.append a a) b
h a b =
add (String.append a b) b
user =
{ name = "Seb"
, score = 42
, city = "Paris"
}
user : User
user =
{ name = "Seb"
, score = 42
, city = "Paris"
}
type alias User =
{ name : String
, score : Int
, city : String
}
newUser =
{ user | score = 43 }
newUserBis =
{ user | score = user.score + 1 }
newUser : User
newUser =
{ user | score = 43 }
newUserBis : User
newUserBis =
{ user | score = user.score + 1 }
rewardUser : User -> User
-- increase the score by one
rewardUser : User -> User
rewardUser user =
{ user | score = user.score + 1 }
Records to store multiple data
(name, score, city....)
Records to store multiple data
(name, score, city....)
What about data following various patterns ?
Point Circle Float Rectangle Float Float
Radius
Length
Width
type Msg
= Increment
| Decrement
First variant
Second variant
Point Circle Float Rectangle Float Float
Radius
Length
Width
Point Circle Float Rectangle Float Float
type Shape =
Point | Circle Float | Rectangle Float Float
myRect = Rectangle 10 20
bigCircle = Circle 420000
describe : ???
describe shape =
case shape of
Point ->
"A lonely point"
Circle radius ->
"A circle of radius "
++ String.fromFloat radius
Rectangle width height ->
"A rectangle of area "
++ String.fromFloat (width*height)
myRect = Rectangle 10 20
bigCircle = Circle 420000
describe : Shape -> String
describe shape =
case shape of
Point ->
"A lonely point"
Circle radius ->
"A circle of radius "
++ String.fromFloat radius
Rectangle width height ->
"A rectangle of area "
++ String.fromFloat (width*height)
Defined by the language
-- Defined by Elm
type Bool = True | False
-- our code:
myBool = True
res =
case myBool of
True -> 42
False -> 18
Defined by the language
-- Defined by Elm
type Bool = True | False
-- our code:
myBool = True
res =
case myBool of
True -> 42
False -> 18
res =
if myBool then
42
else
18
Preferred way:
if(condition) {
myVar = 42;
} else {
myVar = 18;
}
myVar = condition ? 42 : 18;
VS
in imperative language (Java, C, Python...)
in imperative language (Java, C, Python...)
myVar = condition ? 42 : 18;
VS
INSTRUCTION:
changes the state
EXPRESSION:
compute a new value
if(condition) {
myVar = 42;
} else {
myVar = 18;
}
https://ellie-app.com/fF4BSNrDVK4a1
1st step: define Model & Msg and implement update
That's all you need!
[] -- empty list
[1, 2, 6] : List number
["Hello", "world"] : List String
[] -- empty list
[1, 2, 6] : List number
["Hello", "world"] : List String
["Hello", 42] -- impossible!
ages : List Int
ages = [ 18, 14, 35, 10, 51 ]
agesInFiveYears : List Int
agesInFiveYears =
-- add five to each element
addFive : Int -> Int
addFive x = 5 + x
ages : List Int
ages = [ 18, 14, 35, 10, 51 ]
agesInFiveYears : List Int
agesInFiveYears =
List.map addFive ages
List.map :
(a -> b)
-> List a
-> List b
agesInFiveYears =
List.map addFive ages
ages : List Int
ages = [ 18, 14, 35, 10, 51 ]
-- transform into :
-- [ "18 ans", "14 ans", ... ]
-- Hint:
-- String.fromInt : Int -> Str
ages : List Int
ages = [ 18, 14, 35, 10, 51 ]
displayAge : Int -> String
displayAge age =
String.fromInt age ++ " ans"
agesDisplayed =
List.map displayAge ages
{-| Compute the total number of chars in the
list of strings given in argument. Example:
totalLength ["hey!", "I am", "Hungry!!"]
returns 16
-}
totalLength : List String -> Int
totalLength strings = ...
-- HINT: List.sum : List Int -> Int
{-| Compute the total number of chars in the
list of strings given in argument. Example:
totalLength ["hey!", "I am", "Hungry!!"]
returns 16
-}
totalLength : List String -> Int
totalLength strings =
List.sum (List.map String.length strings)
https://ellie-app.com/fF4PS3bjTb7a1
Rules:
By groups of ~2, about 5-10 mins.
-- True if the 1st arg is in the second arg
member : a -> List a -> Bool
-- True if any element of the list is True
any : List Bool -> Bool
-- True if all elements of the list is True
all : List Bool -> Bool
-- rewrite member using map and any
isAscending : List Int -> Bool
implement those functions using recursion and List.foldl (except for the last: use only recursion)
import Dict exposing (Dict)
d1 = Dict.empty
d2 = Dict.insert "Seb" 42 d1
age = case Dict.get "Seb" d2 of
Just a -> "Seb is " ++ String.fromInt a
Nothing -> "I don't know Seb"
d3 =
Dict.fromList [("Seb", 42), ("George", 45)]
associate a key to a value
associate a key to a value
See the docs:
https://package.elm-lang.org/packages/elm/core/latest/Dict
Keys have to be comparable:
String, Int, Float, List and Tuples of comparable are comparable
People list!
https://github.com/sebsheep/intro-to-fp/tree/main/contact-list
Follow the TODOs!
type alias Affectation =
{ varName : String
, value : Int
}
fromString :
String
-> Affectation
fromString "foo = 3"
--{varName="foo",value=3}
Challenges: