前言

我试图围绕如何实际使用ContTcallCC获得有用的信息。我在遵循代码的信息和控制流程时遇到了麻烦。 (但是,这不是延续的重点吗?)

使用此monad可以有很多不同的移动方式,也有少数不是很简单的组合器。我承认我对ContT的工作原理仍然不满意,但是我要指出到目前为止我已经读到的内容:

  • Haskell/Continuation passing style
  • How and why does the Haskell Cont monad work?
  • Understanding Haskell callCC examples
  • Goto in Haskell: Can anyone explain this seemingly insane effect of continuation monad usage?
  • How to interpret callCC in Haskell?
  • Parsec Generally(使我沿这条路入门的文章)

  • 我想做的是发布一个伪代码示例,然后问一些有关它的问题。这代表使用ContT的典型代码外观

    伪代码
    type MyMonad r = ContT r (State SomeState)
    
    main = do
      runState s_init $ runContT block print
    
    block :: MyMonad r a0
    block = do
      before_callcc
      output <- callCC $ \k -> do
        rval <- inner_block
        return rval
      after_callcc
    

    问题
  • 是什么决定output的值和类型?
  • bk类型中是什么意思?
  • 赋予k的值在哪里?
  • 何时运行inner_block?它看到哪个状态的状态?
  • rval会去哪里,它的类型是什么?
  • krval之间是什么关系?
  • 当我在k中应用inner_block,在after_callcc中应用b),在block中应用b,在k之外应用c)时会发生什么?
  • 上面每个状态的状态是什么?
  • 我该怎么办才能从block中获取k
  • 我可以将ojit_code放入状态吗?


  • 颜色编码使阅读更容易

    haskell - ContT Monad : Putting the pieces together-LMLPHP

    最佳答案



    它将与rval具有相同的类型。该值也将是相同的,除非inner_block使用k someValue逃脱了块的其余部分。在这种情况下,output将为someValue



    大致来说,b可以理解为“任何东西”。也就是说,如果inner_block

    ...
    v <- k someValue
    use v
    

    然后v :: b。但是,k someValue将永远不会运行该块的其余部分,因为它将立即退出callCC。因此,将不会返回v的具体值。因此,v可以具有任何类型:use是否需要StringInt都没关系-无论如何它都不会执行。



    内部块一旦运行k someValuecallCC就会将其值返回为output,其余的块将被跳过。



    它在调用callCC时运行,并且看到的状态与我们那时的状态相同。



    放入output中。相同的类型。


    rvalk的参数具有相同的类型。



    a)见上文。
    b)k超出了after_callcc的范围。
    c)也超出范围。



    状态是“当前”状态。 (我不确定您在这里到底要什么)



    我猜想这里需要一个递归类型。这是一个尝试:
    import Control.Monad.Cont
    import Control.Monad.State
    import Control.Monad.Trans
    
    type SomeState = String
    type MyMonad r = ContT r (State SomeState)
    
    newtype K a b r = K ((K a b r, a) -> MyMonad r b)
    
    main = do
      print $ flip runState "init" $ runContT block return
    
    block :: MyMonad r Int
    block = do
      lift $ modify (++ ":start")
      (K myK, output) <- callCC $ \k -> do
        s <- lift $ get
        lift $ modify (++ ":inner(" ++ show (length s) ++")")
        return (K k, 10)
      lift $ modify (++ ":output=" ++ show output)
      s <- lift $ get
      when (length s <50) $ myK (K myK, output+1)
      return 5
    

    此打印
    (5,"init:start:inner(10):output=10:output=11:output=12")
    



    我相信您也需要为此使用递归类型。

    09-30 14:15