我有一个Haskell项目,该项目非常密集地使用fmap数据结构。为了避免一次又一次遍历相同的数据结构,同时保留自由使用的可能性,我决定使用-type来保护一些较大的结构。fmapCoyoneda
Coyoneda类型具有构造函数Coyoneda :: (x -> y) -> f x -> Coyoneda f y。这个想法是通过参数化,更确切地说是通过共同Yooneda引理,类型f a和Coyoneda f a是同构的,但是Coyoneda类型的优点是它延迟了实际的结构遍历。
例如,在下面的代码中,第一个表达式遍历基础结构3次,而第二个表达式仅遍历一次:
fmap k $ fmap h $ fmap g $ (x :: f a)
lowerCoyoneda $ fmap k $ fmap h $ fmap g $ liftCoyoneda $ (x :: f a)
Run Code Online (Sandbox Code Playgroud)
实际上,第二行减少如下:
lowerCoyoneda $ fmap k $ fmap h $ fmap g $ liftCoyoneda $ x
lowerCoyoneda $ fmap k …Run Code Online (Sandbox Code Playgroud) 当我使用-hy标志(用于类型描述)来分析程序的堆使用情况时,例如
./prog +RTS -hy
Run Code Online (Sandbox Code Playgroud)
常常看到->a,->>a,->>>a在结果(其中,a或者是另一种类型的或*)。这是什么意思?
使用StateTmonad 转换器,我可以创建与StateT s [] a同构的类型s -> [(a, s)]。现在我更喜欢使用STTmonad 转换器,因为我想要多个不同类型的可变变量,并且希望能够根据早期计算的结果随意实例化它们。
但是,STT明确提及的链接文档:
这个 monad 转换器不应该与可以包含多个答案的 monad 一起使用,比如列表 monad。原因是状态标记将在不同的答案中重复,这会导致坏事发生(例如失去参考透明度)。安全的 monad 包括 monads State、Reader、Writer、Maybe 以及它们对应的 monad 转换器的组合。
那么我的选择是什么?
完全清楚:
编辑:(编辑编辑:下面的反例是无效的,因为ListT不应该应用于非可交换的 monadST和State。)我开始意识到按照 的方式STT行事的monad 转换器StateT本质上是不安全的。有了它,我们可以构建一个类型STT sloc (ListT (ST sglob)) a。这里,sglob是全局状态sloc的名称,而是局部状态的名称。* 现在我们可以使用全局状态在线程之间交换局部状态引用,从而潜在地获得对未初始化变量的引用。
*为了比较,对应的StateT构造是StateT sloc (ListT (State sglob)) a,与 同构sloc -> …