Большинство монадических функций принимают чистые аргументы и возвращают монадическое значение. Но есть некоторые, которые нужны также монадические аргументы, например:Как кодировать действия, которые принимают монадические аргументы со свободными (или более свободными) монадами?
mplus :: (MonadPlus m) => m a -> m a -> m a
finally :: IO a -> IO b -> IO a
forkIO :: m() -> m ThreadId
-- | From Control.Monad.Parallel
forkExec :: m a -> m (m a)
Каждые из них, кажется, чтобы вызвать различные проблемы, и я не могу получить понимание общего способа, как кодируют таких действий с использованием свободные монады.
В обоих
finally
иforkIO
проблема заключается в том, что монадическая аргумент другого типа, чем результат. Но для бесплатно нужно было бы, чтобы они были одного типа, так какIO a
заменяется переменной типа типа кодировки, напримерdata MyFunctor x = Finally x x x
, которая будет кодировать толькоIO a -> IO a -> IO a
.В From zero to cooperative threads in 33 lines of Haskell code автор использует
Fork next next
в кулак реализацииcFork :: (Monad m) => Thread m Bool cFork = liftF (Fork False True)
, а затем использует его для реализации
fork :: (Monad m) => Thread m a -> Thread m()
, где вход и выход имеют разные типы. Но я не понимаю, было ли это получено с использованием какого-то процесса или просто специальной идеи, которая работает для этой конкретной цели.
mplus
, в частности, в заблуждении: наивное кодирование, какdata F b = MZero | MPlus b b
распределяет над
>>=
и suggested better implementation является более сложным. А также нативная реализация бесплатногоMonadPlus
was removed from free.В freer это реализуется путем добавления
data NonDetEff a where MZero :: NonDetEff a MPlus :: NonDetEff Bool
Почему
MPlus
NonDetEff Bool
вместоNonDetEff a a
? И есть способ, как заставить его работать сFree
, где нам нужен тип данных, чтобы быть функтором, кроме использования CoYoneda functor?- Для
forkExec
Я понятия не имею, как действовать вообще.
Мне кажется, что реализация зависит не от типа функции, а от ее семантики. «Но я не понимаю, получилось ли это с помощью какого-то процесса». Я думаю, что «процесс» здесь просто правильно моделирует ваш домен. Например, я думаю, что кодирование 'finally' было бы более очевидным, если вы сначала попытаетесь закодировать« самые общие »функции исключения (' throw', 'catch'?). Тип 'finally' такой же, как' <* '.. поэтому теоретически нет причин, чтобы функция этого типа не могла быть закодирована (может быть, просто не напрямую ..). – user2407038
@ user2407038 Я понимаю, что вы имеете в виду. Но меня интересует подход «механически закодировать весь интерфейс и позволить интерпретатору беспокоиться о деталях реализации». –