Haskell 不是';t单子本质上只是;概念性;糖
假设Haskell中允许两种类型的函数:Haskell 不是';t单子本质上只是;概念性;糖,haskell,monads,Haskell,Monads,假设Haskell中允许两种类型的函数: 纯粹的(像往常一样) 潜在非纯(程序) f.x.通过声明一个点(“.”)作为函数名的第一个字母将其声明为一个非纯过程来进行区分 此外,我们将制定规则: 纯函数可以由纯函数和非纯函数调用 非纯函数只能由非纯函数调用 和:非纯函数可以强制编程 有了这些语法和规范,还需要单子吗?Monads是否可以做上述规则集不允许的事情 B/c当我开始理解单子时——这正是他们的目的。仅仅是非常聪明的人设法实现了这一点,完全是通过功能方法和一套阴极理论工具。 单子原则
- 纯粹的(像往常一样)
- 潜在非纯(程序)
- 纯函数可以由纯函数和非纯函数调用
- 非纯函数只能由非纯函数调用
- 和:非纯函数可以强制编程
IO
很好地模拟了不纯净的代码,但是Monad
类可以完全正确地用于像State
或Maybe
这样绝对纯净的实例
monad还允许以非常明确的方式表达复杂的上下文层次结构(我选择称之为monad)。“纯净/不纯”并不是你唯一想要区分的。例如,考虑<代码>授权< /代码> /<代码>未授权的< /代码>。可能的用途不胜枚举。。。我鼓励您查看其他常用实例,如ST
、STM
、RWS
、“受限IO”和朋友,以便更好地了解这些可能性
很快,你就可以开始制作自己的单子了,可以根据手头的问题量身定做
B/c当我开始理解单子时——这正是他们的目的
单体在它们的普遍性中与纯度/杂质或强制测序无关。所以不,如果我理解你的问题,单子肯定不是概念上的糖效应封装
考虑到前奏曲中绝大多数单子:列表
,阅读器
,状态
,连续
,或者
,(>)
与效果或IO无关。假设IO是“规范的”单子是一种非常常见的误解,而事实上这是一种退化的情况
B/c当我开始理解单子时——这正是他们的目的
这是哈斯克尔第一篇关于单子的论文:
范畴理论家在20世纪60年代发明了单子,以简洁地表达普遍代数的某些方面
所以你马上就能看到单子与“纯的”/“不纯的”计算无关。世界上最常见的单子是也许是:
data Maybe a
= Nothing
| Just a
instance Monad Maybe where
return = Just
Nothing >>= f = Nothing
Just x >>= f = f x
单子是四元组(可能是,liftM,return,join)
,其中:
liftM :: (a -> b) -> Maybe a -> Maybe b
liftM f mb = mb >>= return . f
join :: Maybe (Maybe a) -> Maybe a
join Nothing = Nothing
join (Just mb) = mb
请注意,liftM
采用非Maybe
函数(非纯!)并将其应用于Maybe
,而join
采用两级Maybe
并将其简化为单层(因此结果中的Just
来自两层Just
:
join (Just (Just x)) = Just x
而结果中的Nothing
可以来自任一层的Nothing
:
join Nothing = Nothing
join (Just Nothing) = Nothing
)。我们可以将这些术语翻译如下:
可能
:可能存在也可能不存在的值
liftM
:将此功能应用于值(如果存在),否则不执行任何操作
return
:获取当前的值,并将其注入到Maybe
的额外结构中
join
:获取一个可能存在或不存在的值(可能存在或不存在),并删除“可能存在或不存在”两层之间的区别
现在,可能是一种非常合适的数据类型。在脚本语言中,它仅通过使用undef
或等价物来表示Nothing
,并以与x
相同的方式表示just x
。在C/C++中,它是通过使用指针类型t*
表示的,并允许指针为NULL
。在Scala中,有一个显式容器类型:。所以你不能说“哦,那只是异常”,因为有异常的语言仍然希望能够在不抛出异常的情况下表示“这里没有值”,然后在有值的情况下应用函数(这就是Scala的选项类型具有foreach
方法的原因)。但是“如果值存在,则应用此函数”正是可能>的>=
所做的!所以这是一个非常有用的操作
您会注意到,C和脚本语言通常不允许对Nothing
和Just Nothing
进行区分——值要么存在要么不存在。在函数式语言中——比如Haskell——允许两个版本是很有趣的,这就是为什么我们需要join
在处理完后消除这种区别。(而且,从数学上讲,用liftM
和join
来定义>=
比用另一种方式更好)
顺便说一句,为了澄清关于Haskell和IO的常见错误概念:GHC实现IO包装器会增加GHC实现I/O的副作用。即使这是GHC糟糕的设计决策——命令式(不同于不纯!)I/O可以在系统的任何级别上进行一元建模,而不存在杂质。你不需要副作用(在系统的任何一层)来做I/O 我只想更强调“不”。monad允许你做很多事情,而不仅仅是添加不纯函数。是的,我只是想给你一些额外的支持我想我只是没有