Jeroen Engels (Yeuroune)
age : Int
age = 29
nom : String
nom = "Jeroen Engels"
Dynamique : Vérification au cours de l'exécution (JavaScript, Python, Clojure, ...)
# Python
>>> "string" + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
Statique : Vérifiés avant l'exécution
(Elm, Java, Haskell, ...)
maFonction : TypeParametre1 -> TypeParametre2 -> TypeDeRetour
maFonction parametre1 parametre2 =
valeurDeLaFonction
variable : Type
variable =
maFonction argument1 argument2
type alias Prenom = String
type alias Nom =
{ prenom : Prenom
, age : Int
}
type Sexe
= Homme
| Femme
| Autre String
quantite : String
quantite = 100 -- NON!
prenom : String -- Garantie par le compilateur
prenom =
"Jeroen"
-- Si jamais on change
prenom : String
prenom =
1000 -- Erreur de compilation
a : (Username -> Username) -> User -> User
a b c =
d (b (e c)) c
addition : number -> number -> number
nomUtilisateur : User -> String
modifiePrenom : (Username -> Username) -> User -> User
type alias RequeteAuServeur data =
{ enCours : Bool
, enErreur : Bool
, données : Maybe data
}
maRequete : RequeteAuServeur String
maRequete =
{ enCours = True
, enErreur = True
, données = Just "Jeroen"
}
type RequeteAuServeur data
= NonDemarree
| EnCours
| EnErreur
| EnSucces data
par Richard Feldman
type alias User =
{ nom : String
-- "admin" ou "user"
, role : String
}
peutSupprimerBaseDeDonnees : User -> Bool
peutSupprimerBaseDeDonnees user =
if user.role == "user" then
False
else
True
user : User
user =
{ nom = "Jeroen Engels"
, role = "User"
}
type alias User =
{ nom : String
, role : Role
}
type Role
= Admin
| User
peutSupprimerBaseDeDonnees : User -> Bool
peutSupprimerBaseDeDonnees user =
case user.role of
Admin -> True
User -> False
type alias User =
{ idUser : String
, idVoiture : String
}
nouvelleVoiture : String -> User -> User
nouvelleVoiture idVoiture user =
{ user | idUser = idVoiture }
type alias User =
{ idUser : UserId
, idVoiture : VoitureId
}
type UserId
= UserId String
type VoitureId
= VoitureId String
nouvelleVoiture : VoitureId -> User -> User
nouvelleVoiture idVoiture user =
{ user | idUser = idVoiture } -- Erreur
type alias User =
{ nom : String
, motDePasse : String
}
modifieMotDePasse : String -> User -> User
modifieMotDePasse motDePasse user =
{ user | motDePasse = motDePasse }
utilisateurAvecMotDePasse =
modifieMotDePasse "a" utilisateur
type alias User =
{ nom : String
, motDePasse : MotDePasseFort
}
type MotDePasseFort
= MotDePasseFort String
modifieMotDePasse : MotDePasseFort -> User -> User
modifieMotDePasse motDePasse user =
{ user | motDePasse = motDePasse }
utilisateurAvecMotDePasse =
modifieMotDePasse (MotDePasseFort "a") utilisateur
module MotDePasseFort exposing
(MotDePasseFort, fromString, comparerMotDePasse, hash)
-- Ne pas faire MotDePasseFort(..)
type MotDePasseFort
= MotDePasseFort String
{-| Si mdp est fort, alors retourne Just mdp, sinon Nothing -}
fromString : String -> Maybe MotDePasseFort
comparerMotDePasse : String -> MotDePasseFort -> Bool
hash : MotDePasseFort -> String
type alias User =
{ nom : String
, motDePasse : MotDePasseFort
}
modifieMotDePasse : MotDePasseFort -> User -> User
modifieMotDePasse motDePasse user =
{ user | motDePasse = motDePasse }
utilisateurAvecMotDePasse =
case MotDePasseFort.fromString "a" of
Just mdp ->
modifieMotDePasse mdp utilisateur
Nothing ->
utilisateur
Limite les opérations possibles sur un type
Cacher l'implémentation (encapsulation)
Opaque par défaut
type Never
= JustOneMore Never
type Never
= JustOneMore Never
a : Never
a =
JustOneMore (JustOneMore (JustOneMore (...
staticHtml : List (Html Never) -> Html Never
type RequeteAuServeur data
= NonDemarree
| EnChargement
| EnErreur
| EnSucces data
reponse : RequeteAuServeur String
reponseAvecUtilisateur : RequeteAuServeur User
-- a n'est pas utilisé
type Fantome a
= Fantome QuelqueChose
type Id data
= Id String
type Voiture = ...
type alias User =
{ voitureId : Id Voiture
}
type Monnaie monnaie
= Monnaie Int
addition : Monnaie m -> Monnaie m -> Monnaie m
euros : Monnaie Euros
euros = Monnaie 1000
dollars : Monnaie Dollars
dollars = Monnaie 100
somme = addition euros dollars -- Erreur!
type Button msg =
Button
{ label : String
, onClick : msg
-- ...
}
withOnClick : msg -> Button msg -> Button msg
------------------------------------------------
view : Html Msg
view =
Button.new
|> Button.withLabel "Clickez-moi!"
|> Button.withOnClick ButtonHasBeenClicked
|> Button.toHtml
view : Html Msg
view =
Button.new
|> Button.withLabel "Clickez-moi!"
-- On ne veut pas un bouton désactivé cliquable!
|> Button.withOnClick ButtonHasBeenClicked
|> Button.disabled
|> Button.toHtml
type Button etat msg =
Button { ... }
new : Button { clickOrDisabled : () } msg
withOnClick :
msg
-> Button { etat | clickOrDisabled : () } msg
-> Button etat msg
disabled :
Button { etat | clickOrDisabled : () } msg
-> Button etat msg
view : Html Msg
view =
Button.new
|> Button.withLabel "Clickez-moi!"
|> Button.withOnClick ButtonHasBeenClicked
-- Erreur du compilateur
-- "Il manque le champ `clickOrDisabled`"
|> Button.disabled
|> Button.toHtml
Jeroen Engels (Yeuroune)
jfmengels sur le Slack Elm