Используйте MonadRef для реализации MonadCont

Существует хорошо известная проблема, котораямы не можем использовать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 типаm b и в соответствии с законом он должен эффективно прекратить вычисление всех дальнейших эффектов), и он получает полученное значение как конечный результатcallCC'.

Итак, мой вопрос:

Является ли эта реализация работает, как ожидается, для идеальногоcallCC? Можем ли мы реализоватьshift а такжеreset с правильной семантикой?

В дополнение к вышесказанному, я хочу знать:

Чтобы обеспечить правильное поведение, мы должны принять некоторые свойстваMonadRef, Так что бы законыMonadRef иметь для того, чтобы заставить вышеупомянутую реализацию вести себя как ожидалось?

ОБНОВИТЬ

Оказывается, вышеописанная наивная реализация недостаточно хороша. Чтобы оно удовлетворяло "Ток продолжения"

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 еще предстоит реализовать.

Ответы на вопрос(1)

Ваш ответ на вопрос