首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell与ContT、callCC的混淆,何时

Haskell与ContT、callCC的混淆,何时
EN

Stack Overflow用户
提问于 2010-02-09 12:56:46
回答 1查看 909关注 0票数 4

继续探索ContT和朋友的意义。请考虑下面(荒谬但说明性的)代码:

代码语言:javascript
复制
v :: IO (Either String [String])
v = return $ Left "Error message"

doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
    x <- liftIO $ v
    x2 <- either (k . Left) return x
    when True $ k (Left "Error message 2")
    -- k (Left "Error message 3")
    return $ Right () -- success

此代码无法编译。但是,如果将when替换为它下面的注释k调用,它就会编译。到底怎么回事?

或者,如果我注释掉x2行,它也会编译。???

显然,这是原始代码的精炼版本,因此所有元素都有其用途。感谢关于正在发生的事情以及如何修复它的解释性帮助。谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-02-09 14:28:54

这里的问题与wheneither的类型有关,而不是ContT的任何特殊问题:

代码语言:javascript
复制
when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c

对于某些monad m,第二个参数需要是m ()类型。因此,您的代码的when行可以像这样修改:

代码语言:javascript
复制
when True $ k (Left "Error message 2") >> return ()

来编译代码。这可能不是您想要做的事情,但是它给了我们一个提示,告诉我们哪里可能是错的:when已经推断出k的类型是不受欢迎的。

现在来看either签名:请注意,either的两个参数必须是生成相同类型结果的函数。这里的return类型由x的类型决定,而v上的显式签名又固定了该类型。因此,(k . Left)位必须具有相同的类型;这反过来将k的类型固定为(由GHC确定)

代码语言:javascript
复制
k :: Either String () -> ContT (Either String ()) IO [String]

这与when的预期不符。

但是,当您注释掉x2行时,它对类型检查器的代码视图的影响将被移除,因此k不再被强制转换为不方便的类型,并且可以自由地采用该类型

代码语言:javascript
复制
k :: Either [Char] () -> ContT (Either [Char] ()) IO ()

这在when的书中是很好的。因此,代码被编译。

最后要注意的是,我使用了GHCi的断点工具来获取这两种场景下k的确切类型--我还远不够专业,无法手工写出它们,也不能以任何方式确保它们的正确性。:-)使用:break ModuleName line-number column-number进行试用。

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

https://stackoverflow.com/questions/2226833

复制
相关文章

相似问题

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