Существует известная проблема:  мы не можем использовать типы forall в Cont возвращаемом типе.
Однако должно быть хорошо, чтобы иметь следующее определение:
class Monad m => MonadCont' m where
    callCC' :: ((a -> forall b. m b) -> m a) -> m a
    shift :: (forall r.(a -> m r) -> m r) -> m a
    reset :: m a -> m a
 а затем найдите экземпляр, который имеет смысл. В в этой статье автор утверждал, что мы можем реализовать MonadFix поверх ContT r m, предоставляя m реализованный MonadFix и MonadRef. Но я думаю, что если у нас есть MonadRef, мы можем фактически реализовать callCC' выше, как показано ниже:
--satisfy law: mzero >>= f === mzero
class Monad m => MonadZero m where
    mzero :: m a
instance (MonadZero m, MonadRef r m) => MonadCont' m where
    callCC' k = do
        ref <- newRef Nothing
        v <- k (\a -> writeRef ref (Just a) >> mzero)
        r <- readRef ref
        return $ maybe v id r
    shift = ...
    reset = ...
(К сожалению, я не знаком с семантикой shift и reset, поэтому я не представил им реализацию)
Эта реализация кажется мне подходящей. Интуитивно, когда вызывается callCC', мы корнем k, который функция, которая имеет свой собственный эффект, всегда терпит неудачу (хотя мы не можем предоставить значение произвольного типа b, но мы всегда можем предоставить mzero of type m b и в соответствии с законом он должен эффективно останавливать вычисления всех последующих эффектов), и он фиксирует полученное значение как окончательный результат callCC'.
Итак, мой вопрос:
Эта реализация работает как ожидалось для идеального callCC? Можем ли мы реализовать shift и reset с правильной семантикой?
В дополнение к вышесказанному, я хочу знать:
Чтобы обеспечить правильное поведение, мы должны взять некоторое свойство MonadRef. Итак, что могли бы сделать законы a MonadRef, чтобы сделать описанную выше реализацию так, как ожидалось?
UPDATE
Получается, что приведенная выше наивная реализация недостаточно хороша. Чтобы он удовлетворял "Току продолжения"
callCC $\k -> k m === callCC $ const m === m
Мы должны настроить реализацию на
instance (MonadPlus m, MonadRef r m) => MonadCont' m where
    callCC' k = do 
       ref <- newRef mzero
       mplus (k $ \a -> writeRef ref (return a) >> mzero) (join (readRef ref))
Другими словами, исходного MonadZero недостаточно, мы должны иметь возможность комбинировать значение mzero с обычным вычислением без отмены всего вычисления.
  Вышеупомянутое не отвечает на вопрос, оно просто корректируется, поскольку исходная попытка была сфальсифицирована как кандидат. Но для обновленной версии исходные вопросы остаются вопросами. Особенно, reset и shift должны быть реализованы.