gpt4 book ai didi

haskell - 在 Haskell 中结合 ST 和 List 单子(monad)

转载 作者:行者123 更新时间:2023-12-04 18:19:42 27 4
gpt4 key购买 nike

使用 StateT monad 转换器,我可以创建类型 StateT s [] a , 与 s -> [(a, s)] 同构.现在我更喜欢使用 STT monad transformer相反,因为我希望拥有多个不同类型的可变变量,并且希望能够根据早期计算的结果随意实例化它们。
但是,STT 的链接文档明确提到:

This monad transformer should not be used with monads that can contain multiple answers, like the list monad. The reason is that the state token will be duplicated across the different answers and this causes Bad Things to happen (such as loss of referential transparency). Safe monads include the monads State, Reader, Writer, Maybe and combinations of their corresponding monad transformers.


那么我的选择是什么?
要完全清楚:
  • 我所追求的是非确定性。我希望能够 fork 我的计算,给每个分支它自己的整个状态的副本。
  • 我不太介意并行性,因为性能不是我最关心的问题。
  • 我不追求的是并发性:不同的计算分支不应该共享可变变量;相反,他们都应该在自己的原始可变变量副本上工作。

  • 编辑:
    (编辑编辑:以下反例无效,因为 ListT 不应应用于非交换单子(monad) STState。)
    我开始意识到 STT monad 转换器,其行为符合 StateT本质上是不安全的。有了它,我们可以构建一个类型 STT sloc (ListT (ST sglob)) a .在这里, sglob是全局状态的名称,而 sloc是本地州的名称。*
    现在我们可以使用全局状态在线程之间交换局部状态引用,从而有可能获得对未初始化变量的引用。
    *为了比较,对应的 StateT build 是 StateT sloc (ListT (State sglob)) a , 与 sloc -> sglob -> ([(a, sloc)], sglob) 同构.

    最佳答案

    你不会绕过StateT ,因为对于这种不确定性的东西,编译器需要始终知道哪些“变量”需要被分支出来。当变量可能潜伏在 STRef 的任何地方时,这是不可能的。 s。

    要仍然获得“不同类型的多个变量”,您需要将它们打包到合适的记录中,并将其用作单个实际状态变量。处理这样的状态对象似乎很尴尬?嗯,使用镜头访问“个体变量”并没有那么糟糕。

    {-# LANGUAGE TemplateHaskell #-}

    import Control.Lens
    import Data.Monoid

    import Control.Monad.Trans.State
    import Control.Monad.ListT
    import Control.Monad.Trans.Class
    import Control.Monad.IO.Class

    data Stobjs = Stobjs {
    _x :: Int
    , _y :: String
    }

    makeLenses ''Stobjs

    main = runListT . (`runStateT`Stobjs 10 "") $ do
    δx <- lift $ return 1 <> return 2 <> return 3
    xnow <- x <+= δx
    y .= show xnow
    if xnow > 11 then liftIO . putStrLn =<< use y
    else lift mempty

    (输出 12)。

    “能够随意实例化它们”有点棘手,因为只有通过更改状态对象才能添加变量,这意味着您将不再真正处于同一个 monad 中。镜头有 zooming 的概念可以使用它——将状态对象拆分为“范围”并使用计算,其中只有一些变量被定义为放大到该范围。

    为了使这真正方便,您需要可以随意扩展的记录。我真的很喜欢 Nikita Volkovs record library approach ,这似乎最近没有进一步发展。 Vinyl也朝那个方向发展,但我没有深入研究。

    future ,我们将拥有 OverloadedRecordFields extension这将有助于解决这类问题。

    关于haskell - 在 Haskell 中结合 ST 和 List 单子(monad),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51874362/

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