首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ContT Monad:把这些片段拼凑在一起

ContT Monad:把这些片段拼凑在一起
EN

Stack Overflow用户
提问于 2015-09-06 01:21:58
回答 1查看 737关注 0票数 11

序言

我正试图思考如何实际使用ContTcallCC来实现一些有用的东西。我在跟踪代码周围的信息和控制流时遇到了困难。(但是,这难道不是延续的意义吗?)

有很多不同的方法可以用这个单子和少数几个不太直接的组合子来移动。我要承认,我仍然对我对ContT工作方式的理解感到不舒服,但我要指出我迄今所读到的内容:

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

Psudo-代码

代码语言:javascript
复制
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

问题

  1. 是什么决定了output的值和类型
  2. bk类型中意味着什么?
  3. k的价值到哪里去了?
  4. inner_block什么时候运行?它看到的是哪一种状态?
  5. rval去哪里了?它的类型是什么?
  6. krval之间的关系是什么?
  7. 当我将k a)应用于inner_block,b)在after_callcc中,c)在block之外时,会发生什么?
  8. 上述每一个状态的版本是什么?
  9. 我需要做些什么才能让k摆脱block
  10. 我能让k进入状态吗?

颜色编码以便于阅读

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-06 06:38:08

  1. 是什么决定了output的值和类型

它将是与rval相同的类型。该值也将相同,除非inner_block使用k someValue来转义块的其余部分。在这种情况下,output将是someValue

  1. bk类型中意味着什么?

粗略地说,b可以理解为“任何东西”。也就是说,如果inner_block

代码语言:javascript
复制
...
v <- k someValue
use v

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

  1. k的价值到哪里去了?

只要内部块运行k someValuecallCC就会以output的形式返回值,并跳过块的其余部分。

  1. inner_block什么时候运行?它看到的是哪一种状态?

它是在callCC被调用时运行的,并且看到了与我们在那一点上相同的状态。

  1. rval去哪里了?它的类型是什么?

转化为output。同样的类型。

  1. krval之间的关系是什么?

rval的类型与k的参数相同。

  1. 当我将k a)应用于inner_block,b)在after_callcc中,c)在block之外时,会发生什么?

( a)见上文。( b) kafter_callcc中超出了范围。( c)也超出了范围。

  1. 上述每一个状态的版本是什么?

国家是“当前”状态。(我不知道你到底想要什么)

  1. 我需要做些什么才能让k摆脱block

我想这里需要一个递归类型。下面是一个尝试:

代码语言:javascript
复制
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

这个指纹

代码语言:javascript
复制
(5,"init:start:inner(10):output=10:output=11:output=12")

  1. 我能让k进入状态吗?

我相信你也需要一个递归类型。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32419145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档