Voici une étape par étape à prendre sur cette question.
Commençons par:
((lenDigits . factorial) 199) <= 199
Selon le Haskell Rapport...
Un littéral entier représente l'application de la fonction fromInteger
de la valeur appropriée de type Integer
.
Cela signifie que la première expression est en réalité:
((lenDigits . factorial) (fromInteger (199 :: Integer))
<= (fromInteger (199 :: Integer))
Par lui-même, fromInteger (199 :: Integer)
a le type polymorphe Num a => a
. Nous avons maintenant à voir si ce type est spécialisée dans le contexte de l'ensemble de l'expression. Notez que, jusqu'à ce que nous trouver une raison pour ne pas l'être, on doit supposer que les types polymorphes de les deux occurrences de fromInteger (199 :: Integer)
sont indépendants (Num a => a
et Num b => b
, si vous voulez).
lenDigits
est Show a => a -> Int
, et donc le...
(lenDigits . factorial) (fromInteger (199 :: Integer))
... à gauche de l' <=
doit être un Int
. Étant donné qu' (<=)
est Ord a => a -> a -> Bool
, l' fromInteger (199 :: Integer)
à la droite de l' <=
doit également être un Int
. L'ensemble de l'expression devient alors:
((lenDigits . factorial) (fromInteger (199 :: Integer)) <= (199 :: Int)
Tandis que le second 199
était spécialisée à l' Int
, le premier est toujours polymorphes. En l'absence d'autres annotations de type, par défaut le rend se spécialiser à l' Integer
lorsque nous utilisons l'expression dans GHCi. Par conséquent, nous obtenons finalement:
((lenDigits . factorial) (199 :: Integer)) <= (199 :: Int)
Maintenant, à la seconde expression:
(\i -> ((lenDigits . factorial) i) <= i) 199
Par le même raisonnement que celui utilisé ci-dessus, (lenDigits . factorial) i
(à la gauche de l' <=
) est un Int
, et ainsi de i
(à droite de l' <=
) est également un Int
. Cela étant, nous avons...
GHCi> :t \i -> (lenDigits . factorial) i <= i
\i -> (lenDigits . factorial) i <= i :: Int -> Bool
... et, par conséquent, en l'appliquant à d' 199
(qui est en fait fromInteger (199 :: Integer)
) se spécialise à int, donnant:
((lenDigits . factorial) (199 :: Int)) <= (199 :: Int)
La première 199
est désormais Int
plutôt que d' Integer
. factorial (199 :: Int)
des dépassements de taille fixe Int
type, conduisant à un résultat erroné. Une façon d'éviter que serait l'introduction explicite fromInteger
afin d'obtenir quelque chose d'équivalent pour le premier scénario:
GHCi> :t \i -> (lenDigits . factorial) i <= fromInteger i
\i -> (lenDigits . factorial) i <= fromInteger i :: Integer -> Bool
GHCi> (\i -> (lenDigits . factorial) i <= fromInteger i) 199
False