Monad和单线程之间的关系是什么?

时间:2015-01-12 00:11:07

标签: haskell monads

当我学习Monod时,我想知道什么路径最适合理解Haskell的Monad。许多人如Bartosz Milewski提出Monads for functional programming是最好的材料。在阅读了本文的一部分后,我得到了同样的感觉,但是在4.2 Array transforms中,我不知道如何理解关于Monad的摘要,因为我错过了第16页底部的基础:

“将M转换为抽象数据类型可确保单个线程 保留,因此使用就地更新实现赋值是安全的。 数据抽象的使用对于此目的是必不可少的。否则,人们可以 编写违反单线程属性的(\x -> (assign i v x ; assign i w x ))等程序。“

我不知道Philip Wadler为什么在这里讨论single threadingdata M a = State -> (a, State)对于保证单线程必须非常重要,为什么?

为此,我实现了本节4.2 Array transforms的代码,其中我假设我的数组与Arr [("ok", 0), ("no", 1)]类似,而index是字符串,值为Int:< / p>

type M a = State -> (a, State)
data Arr = Arr [(Id, Val)] deriving (Show)
type State = Arr
type Id = String
type Val = Int
type Ix = Id

update ix val arr = updateNew ix val arr (Arr [])
           where updateNew ix val (Arr (x:xs)) (Arr newArr) = 
                case (fst x) == ix of
                   True -> Arr (newArr ++ ((ix,val):xs))
                   False -> updateNew ix val (Arr xs) (Arr (newArr ++ [x]))

assign :: Ix -> Val -> M ()
assign i v = \x -> ((), update i v x)

但这对我理解上述摘要没有帮助。我希望有一个热情的人能够解释一下这个问题!

1 个答案:

答案 0 :(得分:3)

在Haskell中,类似[("ok", 0), ("no", 1)]的内容数组*,而是列表。 Haskell列表是不可变的,因此您甚至不必考虑它们的变化。数组是另一个故事。实际上有两个非常不同的东西,都叫做数组:不可变数组和可变数组。

不可变数组只是某些函数的替代表示,以及有关其域的一些信息。

Wadler正在讨论可变阵列,实际上可以更改。我们实际上并没有直接处理这些数组;相反,我们处理作为指针的值。在ML,Java,C等语言中,只要有人访问或修改指向的值,就可以“跟踪”指针。但这将彻底打破Haskell的引用透明度,这对理解和优化它至关重要。

因此,我们所做的是将更改封装到抽象monad中的数组中。各种各样的事情都在破坏规则的范围内进行,但程序员接触到的东西是有道理的。实际上有两个monad可以支持GHC中的可变数组:IOST sST s允许你在一个纯函数中创建一个数组,以各种方式改变它,然后产生一个纯粹的结果。另一方面,IO允许您使用其他IO操作混合数组创建和修改。

*在GHC中,它可能是一个数组,因为GHC提供了一个名为OverloadedLists的扩展,但即使在GHC中,它也很不太可能成为数组。