Я читаю эту реализацию из Continuation в Haskell, и считаю, что большую часть времени это сложно, r
не так важен, поэтому мы предоставляем reset
, чтобы было легкозаменен.
Так что я думаю, что переменную типа r
в Cont r a
не нужно подвергать воздействию, может быть, мы можем просто использовать 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: я не уверен, что тип callCC
вышеправильное одно из моих определений Cont
, может быть, нужно немного отрегулировать.