【问题标题】:Defining bind in the double barrelled continuation Monad in Haskell在 Haskell 的双桶延续 Monad 中定义绑定
【发布时间】:2016-03-30 14:07:12
【问题描述】:

试图在 haskell 中为这个 monad 定义绑定。 如果计算成功,则调用 SCont 延续,如果计算失败,则调用 FCont 延续。

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

【问题讨论】:

  • 你试过用打字孔吗?你在哪里遇到麻烦了?
  • 您不能为裸类型同义词定义“绑定”。您需要将其设为新类型,然后将其声明为 Monad 的实例。
  • 另外,你为什么要() -> Answer 而不仅仅是AnswerAnswer 到底是什么?
  • 是的,我知道我需要让它成为 Monad 的一个实例,但是抛开 Haskell 的形式,我将如何定义它。答案可以是任何东西。
  • 我正在尝试学习在给定 Monad 的情况下定义绑定。这是来自旧的问题表。为什么我想在实践中这样做与我无关

标签: haskell monads continuation-passing


【解决方案1】:

想通了,谢谢你的帮助

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

【讨论】:

    【解决方案2】:

    您对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 的元素,您将遵循相同的过程并到达堆栈 EitherT e (Cont r) a 以获得您的 iso。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 2023-02-26
      • 2011-04-07
      相关资源
      最近更新 更多