Un fait peu connu est que si vous activez suffisamment d'extensions de langage (ghc), Haskell devient un langage interprété à typage dynamique! Par exemple, le programme suivant implémente l'addition.
{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
data Zero
data Succ a
class Add a b c | a b -> c
instance Add Zero a a
instance (Add a b c) => Add (Succ a) b (Succ c)
Cela ne ressemble plus vraiment à Haskell. Pour l'un au lieu d'opérer sur des objets, nous opérons sur des types. Chaque numéro est son propre type. Au lieu de fonctions, nous avons des classes de types. Les dépendances fonctionnelles nous permettent de les utiliser comme fonctions entre types.
Alors, comment invoquer notre code? Nous utilisons une autre classe
class Test a | -> a
where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
=> Test a
Cela définit le type de test
sur le type 4 + 3. Si nous ouvrons cela dans ghci, nous trouverons qu'il test
s'agit bien du type 7:
Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))
Tâche
Je veux que vous implémentiez une classe qui multiplie deux nombres Peano (entiers non négatifs). Les chiffres Peano seront construits en utilisant les mêmes types de données dans l'exemple ci-dessus:
data Zero
data Succ a
Et votre classe sera également évaluée de la même manière que ci-dessus. Vous pouvez nommer votre classe comme vous le souhaitez.
Vous pouvez utiliser toutes les extensions de langage ghc que vous souhaitez sans frais en octets.
Cas de test
Ces cas de test supposent que votre classe est nommée M
, vous pouvez la nommer autrement si vous le souhaitez.
class Test1 a| ->a where test1::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)=>Test1 a
class Test2 a| ->a where test2::a
instance (M Zero (Succ (Succ Zero)) a)=>Test2 a
class Test3 a| ->a where test3::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ Zero) a)=>Test3 a
class Test4 a| ->a where test4::a
instance (M (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) (Succ (Succ (Succ Zero))) a)=>Test4 a
Résultats
*Main> :t test1
test1
:: Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))
*Main> :t test2
test2 :: Zero
*Main> :t test3
test3 :: Succ (Succ (Succ (Succ Zero)))
*Main> :t test4
test4
:: Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))))))))
S'inspire de Taper l'entretien technique