Eine wenig bekannte Tatsache ist, dass Haskell eine dynamisch typisierte interpretierte Sprache wird, wenn Sie genügend Spracherweiterungen (ghc) aktivieren! Das folgende Programm implementiert beispielsweise das Hinzufügen.
{-# 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)
Das sieht nicht mehr wirklich nach Haskell aus. Zum einen operieren wir nicht über Objekte, sondern über Typen. Jede Nummer ist ein eigener Typ. Anstelle von Funktionen haben wir Typklassen. Die funktionalen Abhängigkeiten ermöglichen es uns, sie als Funktionen zwischen Typen zu verwenden.
Wie rufen wir unseren Code auf? Wir benutzen eine andere Klasse
class Test a | -> a
where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
=> Test a
Dies setzt den Typ test
auf den Typ 4 + 3. Wenn wir dies in ghci öffnen, werden wir feststellen, dass test
es sich tatsächlich um Typ 7 handelt:
Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))
Aufgabe
Ich möchte, dass Sie eine Klasse implementieren, die zwei Peano-Ziffern (nicht negative Ganzzahlen) multipliziert. Die Peano-Ziffern werden im obigen Beispiel mit denselben Datentypen erstellt:
data Zero
data Succ a
Und Ihre Klasse wird auf die gleiche Weise wie oben bewertet. Sie können Ihre Klasse nach Belieben benennen.
Sie können beliebige GHC-Spracherweiterungen kostenlos für Bytes verwenden.
Testfälle
In diesen Testfällen wird davon ausgegangen, dass Ihre Klasse benannt M
ist. Sie können sie auch anders benennen , wenn Sie möchten.
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
Ergebnisse
*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)))))))))))))))))
Lässt sich von der Eingabe des technischen Interviews inspirieren