Существует известная проблема, которую мы не можем использовать 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
. Но я думаю, есть ли у нас действительно a 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
таким образом, я не предоставлял реализации им),
Эта реализация кажется OK для меня. Интуитивно, когда callCC'
будучи позвонившимся, мы питаемся k
который функция, что ее собственный эффект всегда является сбоем (хотя мы не можем обеспечить значение произвольного типа b
, но мы можем всегда обеспечивать mzero
из типа m b
и согласно закону это должно эффективно остановить все дальнейшие вычисляемые эффекты), и это получает полученное значение как конечный результат callCC'
.
Таким образом, мой вопрос:
Эта реализация работы как ожидалось для идеала callCC
? Мы можем реализовать shift
и reset
с надлежащим, семантическим также?
В дополнение к вышеупомянутому я хочу знать:
Для обеспечения надлежащего поведения, мы должны принять некоторое свойство MonadRef
. Таким образом, что было бы законы a 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
недостаточно, мы должны смочь к объединенному a mzero
значение с нормальным вычислением, не отменяя целое вычисление.
Вышеупомянутое не отвечает на вопрос, оно просто корректируется, поскольку исходная попытка была сфальсифицирована, чтобы быть кандидатом. Но для обновленной версии, исходными вопросами являются все еще вопросы. Особенно, reset
и shift
должны все еще быть реализованы.
(Это еще не ответ, но только некоторые подсказки подошли в моем уме. Я надеюсь, что это приведет к реальному ответу, один или кем-то еще.)
Вызов по значению является Двойным к Вызову по имени - Philip Wadler
В вышеупомянутой газете, автор представил "Двойное Исчисление", введенное исчисление, которое соответствует классической логике. В последнем разделе существует сегмент, говорит
, стратегия А, двойная к вызову по необходимости, могла избежать этой неэффективности путем перезаписи coterm с его covalue в первый раз, когда это оценено.
, Как указано в статье Wadler, вызов по имени, оценивая продолжения нетерпеливо (это возвращается перед всеми оцениваемыми значениями), пока вызов по значению, оценивая продолжения лениво (это только возвращается после всех оцениваемых значений).
Теперь, смотрите на callCC'
выше, я полагаю, что это - пример двойного из вызова по необходимости в стороне продолжения. Стратегия оценки, это предоставляет поддельное "продолжение" данной функции, но кэширует состояние в этой точке для вызова "истинного" продолжения позже. Это так или иначе похоже на создание кэша продолжения, и поэтому после того как вычисление заканчивается, мы восстанавливаем то продолжение. Но кэшируйтесь, оцененное значение - то, что оно подразумевает под вызовом по необходимости.
В целом я подозреваю, состояние (вычисление до текущего момента времени) является двойным к продолжению (будущее вычисление). Это объяснит несколько явлений. Если это верно, это не удивление, которое MonadRef
(соответствуют глобальному и полиморфному состоянию) является двойным к MoncadCont
(соответствуйте глобальным и полиморфным продолжениям), и таким образом, они могут использоваться для реализации друг друга.