Functor / Applicative Instanzen für Staat in Haskell
-
30-09-2019 - |
Frage
Nach dem Lesen (und einige Abschnitte von Skimming) Wadler Arbeit über Monaden, entschied ich mich an die Arbeit durch das Papier stärker, definieren Funktors und applicative Instanzen für jede der Monaden er beschreibt. Unter Verwendung des Typs Synonym
type M a = State -> (a, State)
type State = Int
Wadler verwendet den Zustand Monade zu definieren, ich habe den folgenden (mit einem damit verbundenen Namen, damit ich sie mit einer newtype Deklaration definieren kann später).
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)
Wenn ich wechsle einen Typkonstruktor in einer newtype Erklärung zu verwenden, z. B.
newtype S a = S (State -> (a, State))
alles auseinander fällt. Alles ist nur eine leichte Modifikation, zum Beispiel,
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))
aber nichts läuft in GHC aufgrund der Tatsache, dass der Lambda-Ausdruck in diesem Typkonstruktor verborgen ist. Nun ist die einzige Lösung, die ich sehe, ist eine Funktion zu definieren:
isntThisAnnoying s (S m) = m s
, um zu binden s 'st' und tatsächlich einen Wert zurückgeben, z. B.
fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s))
Gibt es eine andere Möglichkeit, dies zu tun, die nicht diese Hilfsfunktionen nicht verwendet?
Lösung
Wenn Sie schauen hier , werden Sie sehen, dass sie es auf diese Weise zu definieren:
newtype State s a = State { runState :: (s -> (a,s)) }
, um die innere Lambda einen Namen zu geben.
Andere Tipps
Der üblicher Weg ist newtype newtype S a = S {runState : State -> (a, State)}
zu definieren. Dann statt Ihrer isntThisAnnoying s (S m)
können Sie runState t s
schreiben, wo t
die gleiche wie S m
ist.
Sie haben eine newtype
zu verwenden, da Typ Synonyme nicht typeclass Instanzen sein kann.