在Haskell中的双管延续Monad中定义绑定

时间:2016-03-30 14:07:13

标签: haskell monads continuation-passing

尝试在haskell中为此monad定义bind。 如果计算成功,则调用SCont continuation,如果失败,则调用FCont continuation。

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

2 个答案:

答案 0 :(得分:1)

想出来,谢谢你试图帮助

(xm>> = f)ks kf = xm(\ a f' - > f a ks f')kf

答案 1 :(得分:1)

你给SCont的定义对我来说很奇怪:成功的延续如何将失败作为一个论证?另外,给定returnbind,看起来失败的一个线程一直沿着调用树进行操作,并且......如果你遇到了返回,则应用于成功。

我希望'双管延续Monad'的定义如下:

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

通过推理同构并注意到:

我们可以找到一种系统的方法来定义它(以及它的表兄,其中失败可以采用错误类型e的元素)。
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              

现在,我们可以通过写下这个iso来利用现有的实例:

{-# 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

如果失败继续可以采用错误类型e的元素,那么您将遵循相同的过程并到达您的iso的堆栈EitherT e (Cont r) a