gpt4 book ai didi

haskell - FreeT生成的解释器monad转换器的MonadFix实例?

转载 作者:行者123 更新时间:2023-12-04 11:50:53 25 4
gpt4 key购买 nike

我有一个由 FreeT 生成的标准解释器 monad 转换器的简化版本:

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 ;也就是说,有 Interactive只是一个 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 情况,我也会很高兴:)

最佳答案

想象一下,您已经有了 Interactive 的解释器。 .

interpret :: FreeT (InteractiveF p r) m a -> m a
interpret = undefined

写一个 MonadFix 是微不足道的。实例:
instance MonadFix m => MonadFix (FreeT (InteractiveF p r) m) where
mfix = lift . mfix . (interpret .)

我们可以直接捕捉到这种“了解解释者”的想法,而无需提前指定解释器。
{-# LANGUAGE RankNTypes #-}

data UnFreeT t m a = UnFree {runUnFreeT :: (forall x. t m x -> m x) -> t m a}
-- given an interpreter from `t m` to `m` ^ |
-- we have a value in `t m` of type a ^
UnFreeT只是一个 ReaderT读取解释器。

如果 t是一个单子(monad)变压器, UnFreeT t也是一个monad转换器。我们可以轻松构建 UnFreeT从不需要通过忽略解释器来了解解释器的计算。
unfree :: t m a -> UnFreeT t m a
--unfree = UnFree . const
unfree x = UnFree $ \_ -> x

instance (MonadTrans t) => MonadTrans (UnFreeT t) where
lift = unfree . lift

如果 t是一个单子(monad)变压器, mMonad , 和 t m也是 Monad ,然后 UnFree t mMonad .给定一个解释器,我们可以将两个需要解释器的计算绑定(bind)在一起。
{-# LANGUAGE FlexibleContexts #-}

refree :: (forall x. t m x -> m x) -> UnFreeT t m a -> t m a
-- refree = flip runUnFreeT
refree interpreter x = runUnFreeT x interpreter

instance (MonadTrans t, Monad m, Monad (t m)) => Monad (UnFreeT t m) where
return = lift . return
x >>= k = UnFree $ \interpreter -> runUnFreeT x interpreter >>= refree interpreter . k

最后,给定解释器,只要底层 monad 具有 MonadFix,我们就可以修复计算。实例。
instance (MonadTrans t, MonadFix m, Monad (t m)) => MonadFix (UnFreeT t m) where
mfix f = UnFree $ \interpreter -> lift . mfix $ interpreter . refree interpreter . f

一旦我们有了解释器,我们实际上可以做任何底层 monad 可以做的事情。这是因为,一旦我们有一个 interpreter :: forall x. t m x -> m x我们可以做以下所有事情。我们可以从 m x通过 t m x一直到 UnFreeT t m x并再次退缩。
                      forall x.
lift :: m x -> t m x
unfree :: t m x -> UnFreeT t m x
refree interpreter :: UnFreeT t m x -> t m x
interpreter :: t m x -> m x

用法

为您的 Interactive , 你会包装 FreeTUnFreeT .
type Interactive p r = UnFreeT (FreeT (InteractiveF p r))

您的解释器仍将被编写为产生 FreeT (InteractiveF p r) m a -> m a .解读新的 Interactive p r m a一直到 m a你会用
interpreter . refree interpreter
UnFreeT不再“尽可能地释放解释器”。解释器不再可以随意决定在任何地方做什么。 UnFreeT 中的计算可以请求翻译。当计算请求并使用解释器时,将使用与开始解释程序时相同的解释器来解释程序的那部分。

关于haskell - FreeT生成的解释器monad转换器的MonadFix实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29161923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com