Vielleicht ist das kanonische Beispiel durch die Vektoren gegeben.
data Nat = Z | S Nat deriving (Show, Eq, Ord)
data Vec :: Nat -> * -> * where
V0 :: Vec Z x
(:>) :: x -> Vec n x -> Vec (S n) x
Wir können sie mit ein wenig Aufwand anwendungsfähig machen, zuerst Singles definieren und dann in eine Klasse einwickeln.
data Natty :: Nat -> * where
Zy :: Natty Z
Sy :: Natty n -> Natty (S n)
class NATTY (n :: Nat) where
natty :: Natty n
instance NATTY Z where
natty = Zy
instance NATTY n => NATTY (S n) where
natty = Sy natty
Jetzt können wir die Applicative
Struktur
instance NATTY n => Applicative (Vec n) where
pure = vcopies natty
(<*>) = vapp
vcopies :: forall n x. Natty n -> x -> Vec n x
vcopies Zy x = V0
vcopies (Sy n) x = x :> vcopies n x
vapp :: forall n s t. Vec n (s -> t) -> Vec n s -> Vec n t
vapp V0 V0 = V0
vapp (f :> fs) (s :> ss) = f s :> vapp fs ss
Ich lasse die Functor
Instanz entwickeln (die über fmapDefault
aus der Traversable
Instanz extrahiert werden sollen).
Nun gibt es eine Monad
Instanz entsprechend dieser Applicative
, aber was ist das? Diagonales Denken! Das ist gefragt! Ein Vektor kann als die Tabellierung einer Funktion aus einer endlichen Domäne gesehen werden, daher ist die Applicative
nur eine Tabellierung der K- und S-Kombinatoren, und die Monad
hat ein Reader
ähnliches Verhalten.
vtail :: forall n x. Vec (S n) x -> Vec n x
vtail (x :> xs) = xs
vjoin :: forall n x. Natty n -> Vec n (Vec n x) -> Vec n x
vjoin Zy _ = V0
vjoin (Sy n) ((x :> _) :> xxss) = x :> vjoin n (fmap vtail xxss)
instance NATTY n => Monad (Vec n) where
return = vcopies natty
xs >>= f = vjoin natty (fmap f xs)
Sie könnten ein wenig sparen >>=
durch die Definition von mehr direkt, sondern wie du es schneiden, das monadischen Verhalten schafft nutzlos Thunks für off-diagonal Berechnungen. Faulheit könnte uns vor einer Verlangsamung durch einen Armageddon-Faktor bewahren, aber das Zipping-Verhalten des <*>
wird zwangsläufig etwas billiger sein als die Diagonale einer Matrix.
Vielleicht haben Sie in [The Haxl project] (https://github.com/meiersi/HaskellerZ/blob/master/meetups/20130829-FPAnachmittag_The_Haxl_Project_at_Facebook/The%20Haxl%20Project%20at%20Facebook.pdf?raw=true) auf Facebook interreliert. Erlaubt einen Applicative, der Berechnungen parallelisieren kann. Es ist nicht möglich, Berechnungen mit der monadischen Schnittstelle zu parallelisieren. – bennofs