Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 不是';t单子本质上只是;概念性;糖_Haskell_Monads - Fatal编程技术网

Haskell 不是';t单子本质上只是;概念性;糖

Haskell 不是';t单子本质上只是;概念性;糖,haskell,monads,Haskell,Monads,假设Haskell中允许两种类型的函数: 纯粹的(像往常一样) 潜在非纯(程序) f.x.通过声明一个点(“.”)作为函数名的第一个字母将其声明为一个非纯过程来进行区分 此外,我们将制定规则: 纯函数可以由纯函数和非纯函数调用 非纯函数只能由非纯函数调用 和:非纯函数可以强制编程 有了这些语法和规范,还需要单子吗?Monads是否可以做上述规则集不允许的事情 B/c当我开始理解单子时——这正是他们的目的。仅仅是非常聪明的人设法实现了这一点,完全是通过功能方法和一套阴极理论工具。 单子原则

假设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允许你做很多事情,而不仅仅是添加不纯函数。是的,我只是想给你一些额外的支持我想我只是没有