我有一个由以下生成的标准解释器单子变换器的简化版本FreeT
:
data InteractiveF p r a = Interact p (r -> a)
type Interactive p r = FreeT (InteractiveF p r)
p
是“提示”,并且r
是“环境”......人们可以使用类似的东西来运行它:
runInteractive :: Monad m => (p -> m r) -> Interactive p r m a -> m a
runInteractive prompt iact = do
ran <- runFreeT iact
case ran of
Pure x -> return x
Free (Interact p f) -> do
response <- prompt p
runInteractive prompt (f resp)
instance MonadFix m => MonadFix (FreeT (InteractiveF p r)) m a)
mfix = -- ???
我觉得这种类型或多或少只是StateT
......如果有的话,Interactive p r IO
我认为是IO
......我认为......但是......好吧,无论如何,我的直觉说应该有一个很好的例子。
我试着写一个,但我似乎无法弄清楚。到目前为止,我最接近的尝试是:
mfix f = FreeT (mfix (runFreeT . f . breakdown))
where
breakdown :: FreeF (InteractiveF p r) a (FreeT (InteractiveF p r) m a) -> a
breakdown (Pure x) = x
breakdown (Free (Interact p r)) = -- ...?
我还尝试使用利用MonadFix
实例的版本m
,但也没有运气 -
mfix f = FreeT $ do
rec ran <- runFreeT (f z)
z <- case ran of
Pure x -> return x
Free iact -> -- ...
return -- ...
任何人都知道这是否真的可能,或者为什么不是?如果是的话,我继续寻找的好地方是什么?
或者,在我的实际应用程序中,我什至不需要使用FreeT
...我可以使用Free
; 也就是说,haveInteractive
只是一个 monad 而不仅仅是一个 monad 转换器,并且有
runInteractive :: Monad m => (p -> m r) -> Interactive p r a -> m a
runInteractive _ (Pure x) = return x
runInteractive prompt (Free (Interact p f) = do
response <- prompt p
runInteractive prompt (f response)
如果这种情况有可能而不是一般的 FreeT 情况,我也会很高兴:)