Le système de type de Haskell traite une valeur numérique en fonction?
Question
Après avoir joué avec haskell un peu je suis tombé sur cette fonction:
Prelude Data.Maclaurin> :t ((+) . ($) . (+))
((+) . ($) . (+)) :: (Num a) => a -> (a -> a) -> a -> a
(Data.Maclaurin est exportée par le vecteur de l'espace de l'emballage.) Ainsi, il faut un Num, une fonction, un autre Num et retourne finalement un Nb. Quelle magie fait les travaux suivants?
Prelude Data.Maclaurin> ((+) . ($) . (+)) 1 2 3
6
2 est évidemment pas une fonction (a-> a) ou ne me manque sur quelque chose?
La solution
Le le module de Data.NumInstances
du même paquet définit une instance de Num
pour les fonctions qui renvoient les numéros:
instance Num b => Num (a->b) where
(+) = liftA2 (+)
(*) = liftA2 (*)
fromInteger = pure . fromInteger
...
Dans Haskell un littéral entier comme 2
est générique afin qu'il puisse représenter un numéro pour toute instance de Num
:
Prelude> :t 2
2 :: (Num t) => t
Pour convertir un nombre réel du type requis dans un contexte spécifique, fromInteger
de la classe Num
est appelée.
Etant donné que le module auxiliaire mentionné ci-dessus définit une instance de Num
pour les fonctions, 2
peuvent maintenant être converties en une fonction avec la méthode fromInteger
il spécifiée.
Ainsi, les appels ghci fromInteger 2
pour obtenir la fonction requise comme second paramètre de la construction dans la question. L'expression tout se passe alors d'évaluer à 6
.
Autres conseils
Vous avez de bonnes raisons d'être confondu. Utilisation du module de Data.NumInstances
en GHC (qui est chargé par Data.Maclaurin
), il est possible de contraindre un Num
à une fonction constante.
Prelude Data.NumInstances> :t (2 :: (Num a) => a -> a)
(2 :: (Num a) => a -> a) :: (Num a) => a -> a
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 0
2
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 1000
2
L'évaluation de l'expression est, en substance,
((+) . ($) . (+)) 1 2 3 = ((+) . ($) . (1+)) 2 3
= ((+) (1+)) 2 3
-- (+) is defined for functions that return a Num
= ((+) (1+) (\_ -> 2)) 3
= ((+2) . (1+)) 3
= 6