Haskell 什么';Monad和单线程之间的关系是什么?
当我学习Monod时,我想知道哪条路径最适合理解Haskell的Monad。很多人都认为这是最好的材料。在阅读本文的一部分之后,我得到了同样的感觉,但是在<代码> 4.2数组变换< /代码>中,我不知道如何理解Monad的摘要,因为我错过了第16页底部的一些基础: 将M转换为抽象数据类型可以保证单线程 保留,因此使用就地更新实现分配是安全的。 为此,数据抽象的使用是必不可少的 编写违反单线程属性的程序,如Haskell 什么';Monad和单线程之间的关系是什么?,haskell,monads,Haskell,Monads,当我学习Monod时,我想知道哪条路径最适合理解Haskell的Monad。很多人都认为这是最好的材料。在阅读本文的一部分之后,我得到了同样的感觉,但是在 4.2数组变换< /代码>中,我不知道如何理解Monad的摘要,因为我错过了第16页底部的一些基础: 将M转换为抽象数据类型可以保证单线程 保留,因此使用就地更新实现分配是安全的。 为此,数据抽象的使用是必不可少的 编写违反单线程属性的程序,如(\x->(分配i v x;分配i w x))。” 我不知道Philip Wadler为什么在这里讨
(\x->(分配i v x;分配i w x))
。”
我不知道Philip Wadler为什么在这里讨论单线程<代码>数据MA=State->(a,State)对于保证单线程必须非常重要,为什么
为此,我实现了这一节的代码4.2数组转换
,其中我假设我的数组类似于Arr[(“确定”,0),(“否”,1)]
,并且索引
是字符串,值是Int
:
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)
但这对我理解上述总结没有帮助。我希望一个热情的人能多解释一下 在Haskell中,类似于
[(“ok”,0),(“no”,1)]
的东西不是数组*
,而是列表。Haskell列表是不可变的,因此您甚至不必考虑它们的变化。数组是另一回事。实际上有两种非常不同的东西,都称为数组:不可变数组和可变数组
不可变数组只是某些类型函数的可选表示形式以及有关其域的一些信息
Wadler正在讨论可变数组,它实际上是可以更改的。我们实际上并不直接处理这些数组;相反,我们处理的是作为指向它们的指针的值。在ML、Java、C等语言中,您可以随时“跟随”指针以访问或修改它所指向的值。但这将彻底破坏Haskell的引用透明性,这对理解和优化它至关重要
因此,我们所做的是将对数组的更改封装在一个抽象单子中。各种各样的事情都在幕后进行,违反了规则,但是你,程序员,所接触到的一切都是有意义的。实际上,GHC中有两个单子可以支持可变数组:IO
和sts
sts
允许您在纯函数中生成一个数组,以各种方式对其进行变异,然后生成纯结果<另一方面,code>IO允许您将数组创建和修改与其他IO
操作混合在一起
*
在GHC中,它可能是一个数组,因为GHC提供了一个名为OverloadedList
的扩展,但即使在GHC中,它也不太可能是一个数组。我认为Wadler使用“单线程”的方式与通常的含义只有模糊的关联。他在论文的早期将其定义为,“如果在执行更新操作时没有其他指向数组的指针”,那么该操作是单线程的。因此,诀窍在于显示在程序执行的任何给定点上,对数组的引用只有一个。@DanielWagner,谢谢!在反复读了这篇文章之后,我也看到了这句话并同意你的看法!“我想知道哪条路最适合理解哈斯克尔的单子”。。。首先,没有“哈斯克尔单子”这样的东西。单子的属性可以在各种Haskell类型中找到。然后我们调用这些类型Monad,并使它们成为Monad
type类的实例。这就是全部关于“如何更好地理解单子”,您只需要编写大量代码,然后胡乱处理您认为可能有效的内容。阅读Haskell的一般教程是一个很好的起点。