Die Definition Sie Geben von SCont
ist komisch für mich: Wie kommt die erfolgreiche Fortsetzung der Misserfolg als Argument? Außerdem gibt es return
und bind
, es sieht so aus, als ob der Fehler vollständig in der Aufrufstruktur durchgefädelt wurde und ... auf den Erfolg angewendet wurde, falls Sie eine Rückkehr treffen.
ich die ‚double barreled Fortsetzung Monad‘ wie so definiert werden, erwarten würde:
module SFCont where
import Control.Monad
newtype SFCont r a = SFCont { sfCont :: SCont r a -> FCont r a -> r }
type SCont r a = a -> r
type FCont r a = r
instance Functor (SFCont r) where
fmap f (SFCont c) = SFCont $ \ ks -> c (ks . f)
-- this will be obtained from the definition of the `Monad` instance
instance Applicative (SFCont r) where
pure = return
(<*>) = ap
instance Monad (SFCont r) where
return a = SFCont $ const . ($ a)
m >>= f = SFCont $ \ ks kf -> sfCont m (\ a -> sfCont (f a) ks kf) kf
wir eine systematische Art und Weise zu definieren, es finden kann (und sein Cousin bei denen ein Fehler auf ein Element eines Fehlertyp nehmen e
) durch Argumentation auf Isomorphie und zu merken, dass:
SCont r a -> FCont r a -> r ~{ unfolding SCont, FCont }
(a -> r) -> r -> r ~{ r iso (() -> r) }
(a -> r) -> (() -> r) -> r ~{ uncurrying }
((a -> r), (() -> r)) -> r ~{ ((a -> r), (b -> r)) iso (Either a b -> r) }
(Either a() -> r) -> r ~{ Either a() iso Maybe a }
(Maybe a -> r) -> r ~{ folding MaybeT, Cont }
MaybeT (Cont r) a
und jetzt können wir bestehende Instanzen nutzen, indem sie diese iso aufzuschreiben:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module SFCont where
import Data.Functor.Identity
import Control.Monad
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Cont
newtype SFCont r a = SFCont { sfCont :: SCont r a -> FCont r a -> r }
type SCont r a = a -> r
type FCont r a = r
newtype SFCont' r a = SFCont' { sfCont' :: MaybeT (Cont r) a }
deriving (Functor, Applicative, Monad)
to :: SFCont r a -> SFCont' r a
to m = SFCont' $ MaybeT $ ContT $ \ k -> Identity $
sfCont m (runIdentity . k . Just) (runIdentity $ k Nothing)
from :: SFCont' r a -> SFCont r a
from m = SFCont $ \ ks kf -> runIdentity $
(runContT $ runMaybeT $ sfCont' m) (Identity . maybe kf ks)
instance Monad (SFCont r) where
return = from . return
m >>= f = from $ to m >>= to . f
In dem Fall, in dem die Fehlerfortsetzung ein Element vom Fehlertyp e
annehmen könnte, würden Sie demselben Prozess folgen und für Ihre iso auf dem Stapel EitherT e (Cont r) a
ankommen.
Haben Sie versucht, getippte Löcher zu verwenden? Wo sind Sie in Schwierigkeiten geraten? – dfeuer
Sie können "bind" nicht für ein blankes Synonym definieren. Sie müssen es zu einem neuen Typ machen und es dann als Instanz von Monad deklarieren. –
Warum willst du auch '() -> Answer 'anstatt nur' Answer' und was ist 'Answer'? – dfeuer