L'exemple canonique est peut-être donné par les vecteurs.
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
Nous pouvons les rendre applicatifs avec un petit effort, en définissant d'abord les singletons, puis en les enveloppant dans une classe.
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
Nous pouvons maintenant développer le Applicative
structure
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
J'omets le Functor
(qui devrait être extraite via fmapDefault
de la Traversable
instance).
Maintenant, il y a un Monad
correspondant à cette Applicative
mais qu'est-ce que c'est ? La pensée diagonale ! C'est ce qu'il faut ! Un vecteur peut être considéré comme la tabulation d'une fonction à partir d'un domaine fini, d'où l'expression "vecteur". Applicative
n'est qu'un tableau des combinaisons K et S, et l'élément Monad
a un Reader
-un comportement similaire.
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)
Vous pouvez économiser un peu en définissant >>=
plus directement, mais quelle que soit la façon dont vous le faites, le comportement monadique crée des thunks inutiles pour les calculs hors diagonale. La paresse pourrait nous éviter de ralentir par un facteur d'armageddon, mais le comportement de zippage de l'élément <*>
est forcément un peu moins cher que de prendre la diagonale d'une matrice.