haskell - 如何使免费的 monad 解释器递归?

标签 haskell recursion monads monad-transformers free-monad

Free monad interpreter使用 iterT ,我想要一个内部状态,但我不知道如何做,因为 iterT函数提供延续 f据我所知,预先加载了递归调用。我想一个 StateT包装器是一个可能的解决方案(?),但如果可能的话最好避免。谢谢。

编辑:澄清一下,内部状态是 mval传递给 inner 的参数功能我想分配一个资源并继续使用该资源进行解释。

import Control.Monad.Trans.Free.Church
import Control.Monad.Free.TH

type SomeFree m = FT SomeFreeF m
data SomeFreeF next = SomeAct (() -> next)
deriving instance (Functor SomeFreeF)
makeFree ''SomeFreeF

runSomeFree :: SomeFree IO () -> IO ()
runSomeFree = inner Nothing
  where
  inner mval =
    iterT \case
      SomeAct f -> do
        case mval of
          Nothing -> do
            a <- init
            inner (Just a) (FT someAct f ??)
                       -- How to continue the inner loop with    
                       -- the new state and the continuation `f`?
          Just a -> do
            f a

最佳答案

正如我在评论中指出的,乍一看,这似乎是 iterTM 的工作。 ,就像 iterT除了它在您选择的 monad 转换器中运行。

iterTM :: (Functor f, Monad m, MonadTrans t, Monad (t m)) => (f (t m a) -> t m a) -> FreeT f m a -> t m a
iterTM f (FreeT m) = do  -- running in the output monad `t`
    val <- lift m
    case fmap (iterTM f) val of  -- fold the children first
        Pure x -> return x
        Free y -> f y

你可以选择输出 monad t ,但是 maFreeT 定义您正在折叠的数据结构。对于每一层FreeT ,从底部开始,iterTM通过 f充满了将图层的子元素折叠到回调中的结果。您可以决定如何处理这些 monadic 结果(在它们之间进行选择,对它们进行排序,等等)。

您提到在 StateT 中进行折叠,但您给出的示例代码看起来更像是 ReaderT对我来说。 (您不会从每次迭代中返回修改后的状态 - 只是向下传递修改后的参数。)

runSomeFree :: Monad m => SomeFree m a -> ReaderT (Maybe ()) m a
runSomeFree = iterTM go
    where
        go (SomeAct f) = ask >>= \case
            Just () -> f ()
            Nothing -> local (const $ Just ()) (f ())

关于haskell - 如何使免费的 monad 解释器递归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62444355/

相关文章:

c# - C# 中的 Maybe/Option monad

monads - 使用理由>>

haskell - 在 Haskell 模式匹配中暗示相等

haskell - Haskell 标准库中的 `maximum` 安全吗?

haskell - 代表性双仿函数的不动点

mysql - 通过 Perl(或其他语言)中的 ftp 递归远程目录树,仅将文件层次结构信息填充到 MySQL 中 - 查找现有库

haskell - 在 QuickCheck 中缩小记录的惯用方法

recursion - Rust 会公开调用堆栈深度吗?

javascript - 如何在Javascript中建立相互递归结构?

haskell - Monad 的应用