Cours03 : le système de types¶
-- commentaire : directive pour le compilateur ghc
:opt no-lint
Rappel : Haskell est fortement typé¶
"2" + 3
<interactive>:1:1: error:
• No instance for (Num String) arising from a use of ‘+’
• In the expression: "2" + 3
In an equation for ‘it’: it = "2" + 3
La commande :t peut s'appliquer à n'importe quelle expression Haskell, c'est-à-dire à tout ce que l'on peut évaluer (une valeur, une lettre, un calcul, un if-then-else, une fonction, etc.).
Elle va répondre en donnant:
- soit un type explicite, si c'est le seul possible, par exemple :
:t 'a'
- soit un type polymorphe, qui est un type qui contient une ou plusieurs variables de type
:t []
Ici, le type signifie : une liste d'éléments de n'importe quel type que l'on nomme a. Tous les éléments de liste sont du même type. C'est similaire aux types génériques de Java (par exemple List<A>).
- soit en indiquant une contrainte de classe, la plus générale possible. Par exemple :
:t 1
Ici, le type signifie : n'importe quel type que l'on nomme p, tel que p est membre de la classe Num (c'est la contrainte de classe). Autrement dit, l'expression peut avoir n'importe quel type, à condition que ce type soit "un nombre".
Ces notions seront détaillées dans les sections suivantes.
Les types explicites (ou concrets)¶
Bool— Valeurs logiques.Char— Caractères individuels.Int— Entiers à précision fixe.Integer— Entiers à précision arbitraire.Float— Nombres à virgule flottante à simple précision.Double— Nombres à virgule flottante à double précision.String— Chaînes de caractères (équivalent de[Char]).- les tuples et listes de types explicites
- les fonctions dont les paramètres/types de retour sont explicites
:t "Ab"
:t ['A','b']
:t (True, 'a', "cat")
:t ["True", "'a'", "cat"]
-- avec une annotation de type
:t ["True", "'a'", "cat"] :: [String]
Deux types d'entiers¶
x = 304140932017133780436126081660 :: Int
x
-4849135255881964932
x = 304140932017133780436126081660 :: Integer
x
304140932017133780436126081660
:t 304140932017133780436126081660
Type vs. expression¶
Int n'est pas une expression :
:t Int
<interactive>:1:1: error: Data constructor not in scope: Int
C'est un type, on peut donc demander de quelle sorte (kind) de type il s'agit :
:k Int
Ici, * signifie que c'est un type explicite.
Les variables de type¶
C'est l'équivalent des paramètres de type (type parameter) en Java, c'est-à-dire les lettres entre <>.
-- quel est le type de la fonction head (pour les listes) ?
:t head
Ici, le type signifie : pour n'importe quel type que l'on nomme a, la fonction head prend en paramètre une liste d'éléments de type a et renvoie une valeur de type a.
Une même variable de type désigne le même type dans toute la signature.
:t fst
Ici, le type signifie : pour n'importe quels types que l'on nomme a et b, la fonction fst prend en paramètre un couple d'éléments de type (a,b) et renvoie une valeur de type a.
Les classes de type¶
Une classe de type, c'est (grosso modo) l'équivalent d'une interface en Java. C'est une façon de spécialiser une variable de type pour indiquer quel est le comportement qu'elle implémente.
-- quel est le type de la fonction (==) ?
:t (==)
Ici, le type signifie : pour n'importe quel type que l'on nomme a, tel que a est membre de la classe de type Eq, la fonction (==) prend deux expressions de type a en paramètre et renvoie un booléen.
-- quel est le type de la fonction (+) ?
:t (+)
Ici, le type signifie : pour n'importe quel type que l'on nomme a, tel que a est membre de la classe de type Num, la fonction (+) prend deux expressions de type a en paramètre et renvoie un nombre de même type.
Num n'est pas une expression :
:t Num
<interactive>:1:1: error:
• Data constructor not in scope: Eq
• Perhaps you meant ‘EQ’ (imported from Prelude)
C'est un type, on peut donc demander de quelle sorte (kind) de type il s'agit :
:k Num
Ici, * -> Constraint signifie que Num est une classe applicable à un type et qui produit une contrainte.
-- type explicite vs. classe de type :
:k Int
:k Num
L'analogie avec les interfaces Java ne s'arrête pas là. Une classe de types définit un comportement : additionner, tester l’égalité, comparer l’ordre, énumérer, ...
Les types qui implémentent ce comportement sont des instances de cette classe.
La commande :i permet d'avoir toutes ces informations pour une classe de type.
:i Num
class Num a where
(+) :: a -> a -> a
(-) :: a -> a -> a
(*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
(+), (*), abs, signum, fromInteger, (negate | (-))
-- Defined in ‘GHC.Num’
instance Num Word -- Defined in ‘GHC.Num’
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Int -- Defined in ‘GHC.Num’
instance Num Float -- Defined in ‘GHC.Float’
instance Num Double -- Defined in ‘GHC.Float’
-- quel est le type de la fonction (==) ?
:t (==)
:i Eq
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
(==) | (/=)
-- Defined in ‘GHC.Classes’
instance Eq IHaskellSysIO.IOMode -- Defined in ‘GHC.IO.IOMode’
instance Eq IHaskellSysIO.SeekMode -- Defined in ‘GHC.IO.Device’
instance [safe] Eq IHaskellTH.Extension -- Defined in ‘GHC.LanguageExtensions.Type’
instance (Eq a, Eq b) => Eq (Either a b) -- Defined in ‘Data.Either’
instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
instance Eq Word -- Defined in ‘GHC.Classes’
instance Eq Ordering -- Defined in ‘GHC.Classes’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Eq Float -- Defined in ‘GHC.Classes’
instance Eq Double -- Defined in ‘GHC.Classes’
instance Eq Char -- Defined in ‘GHC.Classes’
instance Eq Bool -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n, Eq o) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l) => Eq (a, b, c, d, e, f, g, h, i, j, k, l) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k) => Eq (a, b, c, d, e, f, g, h, i, j, k) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j) => Eq (a, b, c, d, e, f, g, h, i, j) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i) => Eq (a, b, c, d, e, f, g, h, i) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h) => Eq (a, b, c, d, e, f, g, h) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g) => Eq (a, b, c, d, e, f, g) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f) => Eq (a, b, c, d, e, f) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d, Eq e) => Eq (a, b, c, d, e) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c, Eq d) => Eq (a, b, c, d) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b, Eq c) => Eq (a, b, c) -- Defined in ‘GHC.Classes’
instance (Eq a, Eq b) => Eq (a, b) -- Defined in ‘GHC.Classes’
instance Eq () -- Defined in ‘GHC.Classes’
instance Eq IHaskell.Display.DisplayData -- Defined in ‘IHaskell.IPython.Types’
instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Maybe’
instance Eq IHaskellTH.TypeFamilyHead -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Type -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.TyVarBndr -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.TySynEqn -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.TyLit -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Stmt -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.SourceUnpackedness -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.SourceStrictness -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Safety -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.RuleMatch -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.RuleBndr -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Role -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Range -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Pragma -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Phases -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.PatSynDir -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.PatSynArgs -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Pat -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Overlap -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.NameSpace -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Name -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.ModuleInfo -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Match -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Loc -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Lit -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Inline -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.InjectivityAnn -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Info -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Guard -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.FunDep -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Foreign -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.FixityDirection -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Fixity -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.FamilyResultSig -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Exp -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.DerivStrategy -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.DerivClause -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.DecidedStrictness -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Dec -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Con -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Clause -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Callconv -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Body -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.Bang -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.AnnTarget -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellTH.AnnLookup -- Defined in ‘Language.Haskell.TH.Syntax’
instance Eq IHaskellSysIO.NewlineMode -- Defined in ‘GHC.IO.Handle.Types’
instance Eq IHaskellSysIO.Newline -- Defined in ‘GHC.IO.Handle.Types’
instance Eq IHaskellSysIO.Handle -- Defined in ‘GHC.IO.Handle.Types’
instance Eq IHaskellSysIO.BufferMode -- Defined in ‘GHC.IO.Handle.Types’
instance Eq IHaskellSysIO.HandlePosn -- Defined in ‘GHC.IO.Handle’
instance Eq IHaskell.Display.Widget -- Defined in ‘IHaskell.Types’
instance Eq IHaskell.Display.Display -- Defined in ‘IHaskell.Types’
instance Eq Integer -- Defined in ‘integer-gmp-1.0.3.0:GHC.Integer.Type’
-- quel est le type de la fonction (<) ?
:t (<)
:i Ord
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(<=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(>=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
compare | (<=)
-- Defined in ‘GHC.Classes’
instance Ord IHaskellSysIO.IOMode -- Defined in ‘GHC.IO.IOMode’
instance Ord IHaskellSysIO.SeekMode -- Defined in ‘GHC.IO.Device’
instance (Ord a, Ord b) => Ord (Either a b) -- Defined in ‘Data.Either’
instance Ord a => Ord [a] -- Defined in ‘GHC.Classes’
instance Ord Word -- Defined in ‘GHC.Classes’
instance Ord Ordering -- Defined in ‘GHC.Classes’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Ord Float -- Defined in ‘GHC.Classes’
instance Ord Double -- Defined in ‘GHC.Classes’
instance Ord Char -- Defined in ‘GHC.Classes’
instance Ord Bool -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m, Ord n, Ord o) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m, Ord n) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m, n) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l) => Ord (a, b, c, d, e, f, g, h, i, j, k, l) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k) => Ord (a, b, c, d, e, f, g, h, i, j, k) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j) => Ord (a, b, c, d, e, f, g, h, i, j) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i) => Ord (a, b, c, d, e, f, g, h, i) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h) => Ord (a, b, c, d, e, f, g, h) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g) => Ord (a, b, c, d, e, f, g) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f) => Ord (a, b, c, d, e, f) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d, Ord e) => Ord (a, b, c, d, e) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c, Ord d) => Ord (a, b, c, d) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b, Ord c) => Ord (a, b, c) -- Defined in ‘GHC.Classes’
instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
instance Ord () -- Defined in ‘GHC.Classes’
instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Maybe’
instance Ord IHaskellTH.TypeFamilyHead -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Type -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.TyVarBndr -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.TySynEqn -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.TyLit -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Stmt -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.SourceUnpackedness -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.SourceStrictness -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Safety -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.RuleMatch -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.RuleBndr -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Role -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Range -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Pragma -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Phases -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.PatSynDir -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.PatSynArgs -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Pat -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Overlap -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.NameSpace -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Name -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.ModuleInfo -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Match -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Loc -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Lit -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Inline -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.InjectivityAnn -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Info -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Guard -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.FunDep -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Foreign -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.FixityDirection -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Fixity -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.FamilyResultSig -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Exp -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.DerivStrategy -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.DerivClause -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.DecidedStrictness -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Dec -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Con -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Clause -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Callconv -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Body -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.Bang -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.AnnTarget -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellTH.AnnLookup -- Defined in ‘Language.Haskell.TH.Syntax’
instance Ord IHaskellSysIO.NewlineMode -- Defined in ‘GHC.IO.Handle.Types’
instance Ord IHaskellSysIO.Newline -- Defined in ‘GHC.IO.Handle.Types’
instance Ord IHaskellSysIO.BufferMode -- Defined in ‘GHC.IO.Handle.Types’
instance Ord Integer -- Defined in ‘integer-gmp-1.0.3.0:GHC.Integer.Type’
La commande :i permet également de savoir, pour un type explicite donné, de quelles classes il est une instance.
:i Int
data Int = GHC.Types.I# GHC.Prim.Int#
-- Defined in ‘GHC.Types’
instance Enum Int -- Defined in ‘GHC.Enum’
instance Show Int -- Defined in ‘GHC.Show’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Bounded Int -- Defined in ‘GHC.Enum’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Real Int -- Defined in ‘GHC.Real’
Les principales contraintes de type, leurs dépendances et les types explicites qui les implémentent.¶
-- quel est le type de la fonction sqrt ?
:t sqrt
Ici, le type signifie : pour n'importe quel type de flottant (on a vu Float et Double, par exemple) que l'on nomme a, la fonction sqrt prend en paramètre une valeur de type a et renvoie une valeur de type a.
-- quel est le type de la fonction even ?
:t even
-- quel est le type de la fonction (^) ?
:t (^)
3 ^ 4
81
3.4 ^ 5
454.3542399999999
3 ^ 4.5
<interactive>:1:1: error:
• Could not deduce (Integral b0) arising from a use of ‘^’
from the context: Num a bound by the inferred type of it :: Num a => a at <interactive>:1:1-7
The type variable ‘b0’ is ambiguous
These potential instances exist:
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
...plus 58 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: 3 ^ 4.5
In an equation for ‘it’: it = 3 ^ 4.5
<interactive>:1:5: error:
• Could not deduce (Fractional b0) arising from the literal ‘4.5’
from the context: Num a bound by the inferred type of it :: Num a => a at <interactive>:1:1-7
The type variable ‘b0’ is ambiguous
These potential instances exist:
instance Fractional Double -- Defined in ‘GHC.Float’
instance Fractional Float -- Defined in ‘GHC.Float’
...plus 14 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the second argument of ‘(^)’, namely ‘4.5’
In the expression: 3 ^ 4.5
In an equation for ‘it’: it = 3 ^ 4.5
3 ^ (-4)
Negative exponent
Documentation de la fonction :
(^) :: (Num a, Integral b) => a -> b -> a
raise a number to a non-negative integral power
⚠ Le fait de ne pas pouvoir passer un paramètre négatif n'est pas une contrainte de type. Les classes de type définissent un ensemble de fonctions qui doivent être implémentées, pas des propriétés.
Exemple de variations sur le typage¶
fac :: Int -> Int
fac n = product [1..n]
fac 10
3628800
fac 30
-8764578968847253504
fac2 :: Integer -> Integer
fac2 n = product [1..n]
fac2 30
265252859812191058636308480000000
:t fac2
fac3 :: Int -> Integer
fac3 n = product [1..fromIntegral n]
fac3 30
265252859812191058636308480000000
fac4 n = product [1..n]
fac4 30
265252859812191058636308480000000
:t fac4
fac5 0 = 1
fac5 n = n * fac5 (n-1)
fac5 30
265252859812191058636308480000000
:t fac5
Éléments de correction du TP¶