问题标签 [st-monad]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - Haskell ST Monad:没有(MArray(STArray s)Int(ST s1))的实例
过去一两个月我一直在学习 Haskell,最近解决了这个编码问题。额外的挑战是在没有额外空间和线性时间的情况下完成任务,我认为这不可能以纯粹的功能方式完成,所以我自然而然地发现了 ST monad,我认为这将是一个很好的机会了解更多信息。无论如何,这是我写的代码:
这个想法是使用 1 ≤ a[i] ≤ n 的前提条件,并且每个元素最多出现 2 次。但是代码给了我以下错误。
我希望有人能指出我正确的方向!
haskell - 在 ST monad 中隐藏幻像类型
我正在为 Haskell 中的一种简单的命令式编程语言编写一个(小步)解释器。我想在 IO monad 之外进行评估,因此我试图将 ST monad 用于可变变量。但是我意识到这意味着向我的值类型引入一个新的幻像类型变量,但是我的表达式类型也需要它,然后我的语句类型也需要它,等等第四。
我的问题是,有什么好的方法可以避免这个问题。我可以以某种方式隐藏幻像类型吗?我试图通过forall s.
在我的 AST 定义中引入 a 来做到这一点,但编译器对此并不满意。
haskell - 将 ST monad 重新打扮成类似于 State monad 的东西
场景如下:Given 是一个 C 库,其核心是一些结构,其上的操作由大量 C 函数提供。
第 1 步:使用 Haskell 的FFI创建一个包装器。它具有myCLibInit :: IO MyCLibObj
、myCLibOp1 :: MyCLibObj -> ... -> IO ()
等功能。MyCLibObj
是一个不透明类型,它携带(并隐藏) aPtr
或ForeignPtr
实际的 C 结构,例如在本wiki或RWH ch. 17 .
第 2 步:使用unsafeIOToST
fromControl.Monad.ST.Unsafe
将所有IO
动作转换为ST
动作。这是通过引入类似的东西来完成的
然后将所有IO
函数包装在ST
函数中,例如:
这允许编写反映使用类似 OO 的 C 库的命令式程序,例如:
第 3 步:MyCLibObj
通常将多个操作混合在一个 do-block上是没有意义的。例如,当 C 结构是(或应该被认为是)单例实例时。做类似doSomething
上面的事情要么是荒谬的,要么是完全禁止的(例如,当 C 结构是 a 时static
)。在这种情况下,类似于State
monad 的语言是必要的:
在哪里
这就引出了一个问题:如何将ST s a
monad 重新打扮成更像State
monad 的东西。由于withMyCLibInstance
将使用runST
新的 monad 函数,我们称之为Q
(对于 'q'uestion),应该是
这对我来说看起来很奇怪。我已经在Functor
为此实现实例而苦苦挣扎Q
,更不用说Applicative
和Monad
. ST s
实际上已经是一个 monad,但是 states
不能逃脱ST
monad,因此forall s. ST s a
. 这是摆脱的唯一方法,s
因为runST :: (forall s. ST s a) -> a
,并且withMyCLibInstance
只是 amyCLibInit'
后跟 a runST
。但不知何故,这不合适。
处理第 3 步的正确方法是什么?我应该做第 2 步,还是Q
在第 1 步之后滚动我的权利?我的感觉是这应该很简单。ST
单子有我需要的一切,只是Q
需要以正确的方式设置......
更新 1:步骤 3 中的单例和静态结构示例不是很好。如果两个这样的 do 块并行执行,可能会发生非常糟糕的事情,即两个 do 块将并行处理同一个 C 结构。
haskell - 在 Haskell 中结合 ST 和 List 单子
使用StateT
monad 转换器,我可以创建与StateT s [] a
同构的类型s -> [(a, s)]
。现在我更喜欢使用STT
monad 转换器,因为我想拥有多个不同类型的可变变量,并且希望能够根据早期计算的结果随意实例化它们。
STT
但是,明确提及的链接文档:
这个单子转换器不应该与可以包含多个答案的单子一起使用,例如列表单子。原因是状态令牌将在不同的答案中重复,这会导致坏事发生(例如失去参考透明度)。安全单子包括单子 State、Reader、Writer、Maybe 以及它们相应的单子转换器的组合。
那么我的选择是什么?
要完全清楚:
- 我所追求的是非确定性。我希望能够分叉我的计算,给每个分支它自己的整个状态的副本。
- 我不太介意并行性,因为性能不是我最关心的问题。
- 我不追求的是并发性:不同的计算分支不应该共享可变变量;相反,他们都应该在自己的原始可变变量副本上工作。
编辑:(编辑编辑:以下反例无效,ListT
不应应用于非交换单子和ST
。State
)我开始意识到,STT
按照 StateT
有了它,我们可以构建一个 type STT sloc (ListT (ST sglob)) a
。这里,sglob
是全局状态sloc
的名称,而是局部状态的名称。* 现在我们可以使用全局状态在线程之间交换局部状态引用,从而有可能获得对未初始化变量的引用。
*为了比较,对应的StateT
结构是StateT sloc (ListT (State sglob)) a
,它同构于sloc -> sglob -> ([(a, sloc)], sglob)
.
haskell - `State#` 的规范
但是,文档STT
说:
这个单子转换器不应该与可以包含多个答案的单子一起使用,例如列表单子。原因是状态令牌将在不同的答案中重复,这会导致坏事发生(例如失去参考透明度)。安全单子包括单子 State、Reader、Writer、Maybe 以及它们相应的单子转换器的组合。
我希望能够自己判断对STT
monad 的某种使用是否安全。特别是,我想了解与 List monad 的交互。我知道那STT sloc (ListT (ST sglob)) a
是不安全的,但是呢STT sloc []
?
我发现(至少在 GHC 中)最终是使用,等STT
神奇的构造实现的。是否有任何关于这些对象如何表现的准确文档?MuteVar#
State#
realWorld#
这与我之前的一个问题密切相关。
haskell - Data.Vector 的 unsafeFreeze/unsafeThaw 到底有多“不安全”?
Unsafe[ly] 在不复制的情况下将可变向量转换为不可变向量。在此操作之后可能无法使用可变向量。
我想准确描述“不安全”在这里的含义。从实验上看,它似乎“仅”暗示对原始可变向量的进一步修改将导致由返回的不可变向量unsafeFreeze
不再是纯的:
我可以想象修改在“不安全”冻结中使用的源代码会做各种会导致更糟糕的行为的粗糙的事情,例如段错误。不幸的是,我很快就试图阅读有关不安全操作的源代码。
我可以依靠上述杂质作为这些操作“不安全”的唯一方式吗?
对于上下文:我需要在典型的不可变数据结构上实现各种修改算法,并且在内部可变性范围内不重用其面向公众的 API 将非常不方便(因为 AFAICT 无法通用访问这两个可变数据和不可变向量)。(Ab)unsafeFreeze
当我需要使用该 API 时使用将是完美的逃生舱口,只要我不让自己在路上遇到更多不愉快的副作用。
haskell - 修改 ReaderT 中的 ST 依赖环境 – `local` 函数的问题
这个问题是这个线程的续集:https ://stackoverflow.com/a/54317095/4400060
我在那里询问有关携带STRef
的ReaderT
环境并在其下执行 ST-actions 的问题。我的设置现在看起来像:
总的来说它很酷——我可以dataspace
自由地访问或修改。但是,当我添加不可变时,namespace
我开始挣扎。我需要的功能是以不会影响进一步计算的命名空间的方式运行Comp
更新的操作namespace
——正是这样local
做的。
首先,我想为 编写MonadReader
实例Comp
,但是我遇到了ST
的幻像类型并得到了illegal instance
错误:
完整的错误信息:
我理解这个错误,但我认为没有办法绕过它。老实说,我并不需要完整local
的功能。我只需要能够以Comp
不同namespace
但相同的方式运行dataspace
。
最好的解决方案是提供完整的MonadReader
实例。我知道这可能是不可能的,所以作为一种解决方法,我想要一个函数
总结:我希望能够在Comp
修改后运行,namespace
同时保持dataspace
不变作为参考,保留所有更改。
怎么做?如果需要,我可以接受修改我的初始设置。
dictionary - 用于在地图上插入和总查找的 Monad 转换器?
我有一个计算,我将值插入到 a 中Map
,然后再次查找它们。我知道在插入之前我从来没有使用过钥匙,但(!)
随意使用会让我感到紧张。我正在寻找一种方法来获得一个不返回 a 的总查找函数,Maybe
并且类型系统可以防止我意外滥用。
我的第一个想法是制作一个类似于 的 monad 转换器StateT
,其中状态为 aMap
并且在 monad 中有用于插入和查找的特殊功能。insert 函数返回一个Receipt s k
newtype,其中s
是ST
monad风格的幻象索引类型,k
是 key 的类型,lookup 函数采用 aReceipt
而不是裸 key。通过隐藏Receipt
构造函数并使用类似于 的量化运行函数runST
,这应该确保仅在插入同一映射后发生查找。(完整代码如下。)
但我担心我重新发明了一个轮子,或者担心有另一种方法可以安全地进行全地图查找,并且已经在使用中。在某处的公共包中是否有针对此问题的现有技术?
编辑:一些评论者问我为什么要保留 aReceipt
而不是实际值。我希望能够使用Receipt
in Set
s 和Map
s (我没有在我的 MVCE 中添加Eq
andOrd
实例Receipt
,但我的项目中有它们),但我的值Map
是不相等的。如果我Receipt
用键值对 newtype 替换,我将不得不Eq
为该对实现一个不诚实的实例,而忽略该值,然后我会对此感到紧张。这Map
是为了确保在任何给定时间我的任何等效“代理”键都只考虑一个值。
我想一个对我来说很好的替代解决方案是一个 monad 转换器,它提供Ref
s 的供应,其中data Ref v = Ref Int v
monad 确保Ref
s 以唯一的Int
ID 给出,Eq Ref
等等。只看Int
(现在诚实由Int
s) 的唯一性保证。我也会接受指向野外这种变压器的指针。
loops - 在 ST monad 内循环
我正在尝试在 Haskell 上实现插入排序Data.Array.ST
,并使用一元比较函数。即,sortByM :: (Monad m, Ix i, Enum i, Eq i) => (e -> e -> Ordering) -> STArray s i e -> m (ST s ())
。这是我的代码,用于上下文:
据我了解,我遇到的问题是loopM
' 的第一个参数应该有 type ST s i -> m (Either i (ST s ()))
,但由于runST
' 隐藏ST
内部状态的方法,fmap (mapLeft runST) . bubbleBackOnce ary
有 type (forall s'. ST s' i) -> Either i (ST s i)
。这是我第一次使用 ST,所以我不知道如何解决这个问题。此外,这是一个宠物项目,所以我试图避免依赖现有的可以简化事情的库,例如STMonadTrans。
refactoring - 将 ST 计算移至子计算
我ST
使用随机数运行以下代码:
我想重构generate
,以便计算的整个尾部不是在 a 下case
,而是(assassins2, others2)
在子计算中计算,即我想这样重写它:
我相信这应该是一个等效的转换。但是,第二个版本无法通过以下方式进行类型检查: