我正在阅读在Haskell中延续的this implementation,我发现它很棘手,大多数时候,r并不是那么重要,所以我们提供了reset来让它更容易被替换。
因此,我认为Cont r a中的r类型变量没有必要公开,也许我们可以只使用forall r将r隐藏在Cont的定义中,所以下面是我的尝试:
{-# language RankNTypes #-}
data Cont a = MkCont {runCont :: forall r. (a -> r) -> r}
-- try to construct a Cont
c1 :: Cont Int
c1 = MkCont ($ 1)
evalCont :: Cont a -> a
evalCont c = runCont c id
-- mapCont is useless since `f` can only be `id` now
mapCont :: (forall r. r -> r) -> Cont a -> Cont a
mapCont f c = (MkCont (f . runCont c))
withCont :: (forall r. (b -> r) -> a -> r) -> Cont a -> Cont b
withCont f c = MkCont (runCont c . f)
-- reset is unnecessary since `r` is hidden
reset :: Cont a -> Cont a
reset = id
shift :: (forall r. (a -> r) -> Cont r) -> Cont a
shift f = MkCont (evalCont . f)
-- don't know how to define `callCC` now ...
callCC :: ((a -> Cont b) -> Cont a) -> Cont a
callCC = undefined -- this definition seems impossible to implement但是我在尝试定义和实现callCC时遇到了一个问题,如果我引用传统的定义,那么它应该是
callCC f = MkCont $ \c1 -> runCont (f (\x -> MkCont $ \c2 -> c1 x)) c1但是上面的代码没有类型检查,所以我是犯了什么愚蠢的错误,还是不可能像这样定义Cont?
PS:我不确定在我对Cont的定义中,上述类型的callCC是不是合适的,也许它需要一些调整。
发布于 2019-09-24 19:41:18
这个单体(转换器)也称为Codensity:https://hackage.haskell.org/package/kan-extensions-5.2/docs/Control-Monad-Codensity.html
您实际上也没有实现reset,除了类型之外还有更多的东西。必须满足以下等式:
移位复位(
f >>= k) =复位(f (evalCont .k))
-- https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-Trans-Cont.html#v:shift
https://stackoverflow.com/questions/58077208
复制相似问题