Я думал, что правильным типом для ContT должен быть
newtype ContT m a = ContT {runContT :: forall r. (a -> m r) -> m r}
и другие операторы управления
shift :: Monad m => (forall r. (a -> ContT m r) -> ContT m r) -> ContT m a
reset :: Monad m => ContT m a -> ContT m a
callCC :: ((a -> (forall r. ContT m r)) -> ContT m a) -> ContT m a
К сожалению, я не могу выполнить проверку типа callCC
и не знаю, как это сделать. сделай это.
Мне удалось сделать shift
и reset
type check
reset :: Monad m => ContT m a -> ContT m a
reset e = ContT $ \ k -> runContT e return >>= k
shift :: Monad m => (forall r. (a -> ContT m r) -> ContT m r) -> ContT m a
shift e = ContT $ \ (k :: a -> m r) ->
runContT ((e $ \ v -> ContT $ \c -> k v >>= c) :: ContT m r) return
, но я все равно не могу использовать shift
и reset
в рекурсивных переходах как это?
newtype H r m = H (H r m -> ContT m r)
unH (H x) = x
test = flip runContT return $ reset $ do
jump <- shift (\f -> f (H f))
lift . print $ "hello"
unH jump jump
Кто-нибудь пробовал это раньше?