2016-03-30 8 views
-1

Der Versuch, die Bindung für diese Monade in Haskell zu definieren. Wenn die Berechnung erfolgreich ist, wird die SCont-Fortsetzung aufgerufen. Wenn sie fehlschlägt, wird die FCont-Fortsetzung aufgerufen.Definieren der Bindung in der doppelstreifigen Folge Monad in Haskell

type M a = SCont a -> FCont -> Answer 
type SCont a = a -> FCont -> Answer 
type FCont =() -> Answer 

result :: a -> M a 
result x ks kf = ks x kf 

(>>=) :: M a -> (a -> M b) -> M b 
+0

Haben Sie versucht, getippte Löcher zu verwenden? Wo sind Sie in Schwierigkeiten geraten? – dfeuer

+2

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. –

+1

Warum willst du auch '() -> Answer 'anstatt nur' Answer' und was ist 'Answer'? – dfeuer

Antwort

1

es heraus, Dank für den Versuch

(xm >> = f) zu helfen ks kf = xm (\ af '-> fa ks f') kf

1

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.