instances foncteurs / Applicative pour État à Haskell
-
30-09-2019 - |
Question
Après avoir lu (et écrémage certaines sections) papier de Wadler sur monades, j'ai décidé de travailler à travers le papier de plus près, la définition foncteur et instances pour chacun des applicatifs monades qu'il décrit. En utilisant le synonyme de type
type M a = State -> (a, State)
type State = Int
Wadler utilise pour définir la monade de l'Etat, je donne les résultats suivants (en utilisant des noms connexes afin que je puisse les définir avec une déclaration newtype plus tard).
fmap' :: (a -> b) -> M a -> M b
fmap' f m = \st -> let (a, s) = m st in (f a, s)
pure' :: a -> M a
pure' a = \st -> (a, st)
(<@>) :: M (a -> b) -> M a -> M b
sf <@> sv = \st -> let (f, st1) = sf st
(a, st2) = sv st1
in (f a, st2)
return' :: a -> M a
return' a = pure' a
bind :: M a -> (a -> M b) -> M b
m `bind` f = \st -> let (a, st1) = m st
(b, st2) = f a st1
in (b, st2)
Quand je passe à l'aide d'un constructeur de type dans une déclaration newtype, par exemple.
newtype S a = S (State -> (a, State))
tout se désagrège. Tout est juste une légère modification, par exemple,
instance Functor S where
fmap f (S m) = S (\st -> let (a, s) = m st in (f a, s))
instance Applicative S where
pure a = S (\st -> (a, st))
cependant rien à court GHC en raison du fait que l'expression lambda est caché dans ce constructeur de type. Maintenant, la seule solution que je vois est de définir une fonction:
isntThisAnnoying s (S m) = m s
, afin de se lier à s 'st' et retrouver en fait une valeur, par ex.,
fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s))
Y at-il une autre façon de faire qui n'utilise pas ces fonctions auxiliaires?
Autres conseils
La manière habituelle est de définir newtype newtype S a = S {runState : State -> (a, State)}
. Alors, au lieu de votre isntThisAnnoying s (S m)
vous pouvez écrire runState t s
où t
est le même que S m
.
Vous devez utiliser un newtype
car synonymes de type ne peuvent pas être des instances classe de types.