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
la source
Réponses:
130121 octets-9 octets grâce à Ørjan Johansen
Essayez-le en ligne!
Ceci définit des familles de types fermées pour l'addition
(+)
et la multiplication(*)
. Ensuite, une classe de type(#)
est définie qui utilise le(*)
famille de types avec une contrainte d'égalité pour convertir du monde des familles de types au monde des prologues de classe de types.la source
Zero
parz
.+
est utile?139 octets
Essayez-le en ligne!
Définit un opérateur de type
*
. Equivalent au programme Prolog:Potato44 et Hat Wizard ont enregistré 9 octets chacun. Merci!
la source
f
au lieu deSucc
.Version familiale, 115 octets
Essayez-le en ligne!
Il s'agit d'une famille de type fermée comme celle de potato44 . Sauf contrairement à l'autre réponse, je n'utilise qu'une seule famille de types.
Cela définit un opérateur sur trois types. Il implémente essentiellement
(a*b)+c
. Chaque fois que nous voulons ajouter notre argument de droite au total, nous le mettons à la place dans l'accumulateur.Cela nous empêche d'avoir à définir
(+)
du tout. Techniquement, vous pouvez utiliser cette famille pour implémenter l'addition en faisantVersion de classe, 137 octets
Essayez-le en ligne!
Cette version de classe perd du terrain par rapport à la version familiale, mais elle est toujours plus courte que la version de classe la plus courte ici. Il utilise la même approche que ma version familiale.
la source
Constraint
. Vous devez donc mettre à jour la spécification ou revenir au formulaire qui utilise une classe au lieu d'un synonyme de type. Si je devais utiliser le synonyme de type, je pourrais obtenir ma réponse à 96 octets, donc cela me fait gagner un octet de plus que vous