Haskell 与 ContT、callCC 混淆,当
继续寻求理解 ContT 和朋友们的意义。请考虑下面的(荒谬但说明性的)代码:
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 行,它也会编译。 ???
显然,这是原始代码的精炼版本,因此所有元素都有其用途。感谢有关发生的情况以及如何解决问题的解释性帮助。谢谢。
Continuing quest to make sense of ContT and friends. Please consider the (absurd but illustrative) code below:
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
This code does not compile. However, if the replace the when
with the commented k call below it, it compiles. What's going on?
Alternatively, if I comment out the x2 line, it also compiles. ???
Obviously, this is a distilled version of the original code and so all of the elements serve a purpose. Appreciate explanatory help on what's going on and how to fix it. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的问题与
when
和either
的类型有关,与 ContT 无关:第二个参数需要是
m ()
类型code> 对于一些 monadm
。因此,可以像这样修改代码的when
行:以使代码编译。这可能不是您想要做的,但它给了我们一个关于可能出现错误的提示:
k
的类型已被推断为when
难以接受的类型。现在对于
either
签名:请注意,either
的两个参数必须是产生相同类型结果的函数。这里return
的类型由x
的类型决定,而x
的类型又由v
上的显式签名确定。因此,(k . Left)
位必须具有相同的类型;这又将k
的类型修复为(GHC 确定的),这与
when
的期望不兼容。但是,当您注释掉
x2
行时,它对类型检查器的代码视图的影响将被消除,因此k
不再被强制为不方便的类型并且是免费的假设when
书中合适的类型。这样,代码就可以编译了。最后一点,我使用 GHCi 的断点工具在两种情况下获取了
k
的确切类型——我还不够专业,无法用手写出它们并以任何方式保证他们的正确性。 :-) 使用:break ModuleName line-number column-number
来尝试一下。The problem here has to do with the types of
when
andeither
, not anything particular to ContT:The second argument needs to be of type
m ()
for some monadm
. Thewhen
line of your code could thus be amended like so:to make the code compile. This is probably not what you want to do, but it gives us a hint as to what might be wrong:
k
's type has been inferred to be something unpalatable towhen
.Now for the
either
signature: notice that the two arguments toeither
must be functions which produce results of the same type. The type ofreturn
here is determined by the type ofx
, which is in turn fixed by the explicit signature onv
. Thus the(k . Left)
bit must have the same type; this in turn fixes the type ofk
at (GHC-determined)This is incompatible with
when
's expectations.When you comment out the
x2
line, however, its effect on the type checker's view of the code is removed, sok
is no longer forced into an inconvenient type and is free to assume the typewhich is fine in
when
's book. Thus, the code compiles.As a final note, I used GHCi's breakpoints facility to obtain the exact types of
k
under the two scenarios -- I'm nowhere near expert enough to write them out by hand and be in any way assured of their correctness. :-) Use:break ModuleName line-number column-number
to try it out.