Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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 为什么我们需要单子而不是单子_Haskell_Functional Programming_Monads_Maybe_Either - Fatal编程技术网

Haskell 为什么我们需要单子而不是单子

Haskell 为什么我们需要单子而不是单子,haskell,functional-programming,monads,maybe,either,Haskell,Functional Programming,Monads,Maybe,Either,我在玩Maybe和monad类型(链接,根据返回值应用条件函数,还返回错误消息链接函数失败等等)。所以在我看来,我们可以通过使用任何一个单子来实现相同的和更多的事情。所以我的问题是,它们之间的实际或概念上的区别在哪里?你当然是对的,可能a与任一单元a同构。问题是,它们通常在语义上用于表示不同的事物,有点像返回null和抛出NoSuchElementException之间的区别: Nothing/None表示“预期的”缺失,而 Left e表示由于任何原因在获取它时出错 也就是说,我们甚至可以

我在玩Maybe和monad类型(链接,根据返回值应用条件函数,还返回错误消息链接函数失败等等)。所以在我看来,我们可以通过使用任何一个单子来实现相同的和更多的事情。所以我的问题是,它们之间的实际或概念上的区别在哪里?

你当然是对的,
可能a
任一单元a
同构。问题是,它们通常在语义上用于表示不同的事物,有点像返回
null
和抛出
NoSuchElementException
之间的区别:

  • Nothing
    /
    None
    表示“预期的”缺失,而
  • Left e
    表示由于任何原因在获取它时出错
也就是说,我们甚至可以将这两者结合起来:

query :: Either DBError (Maybe String)
其中,我们表示了缺失值(DB
NULL
)和连接、数据库管理系统或其他方面的错误的可能性(不是说没有更好的设计,但你明白了)

有时,边界是流动的;对于
saveHead::[a]>可能是一个
,我们可以说错误的预期可能性是按照函数的意图编码的,而类似于
saveDivide
的东西可能被编码为
Float->Float->FPError Float
Float->Maybe Float
,具体取决于用例(同样,只是一些愚蠢的例子…)


如果有疑问,最好的选择可能是使用带有语义编码的自定义结果ADT(如
data QueryResult=Success String | Null | Failure DBError
),并且更喜欢
Maybe
,而不是“传统预期”的简单情况(这是一个主观点,但如果您获得了经验,这基本上是可以的).

@phg的答案很好。我会在学习它们的时候提出一些帮助我澄清问题的建议:

  • 可能
    是一(值)或无–即,你有值或你什么都没有
  • 或者
    是一个逻辑析取,但您总是至少有一个(值)-即,您有一个或另一个,但不是两个都有
可能
适用于您可能有价值或可能没有价值的情况,例如在列表中查找某个项目。如果列表中包含该项目,我们会得到
(可能是x)
,否则我们会得到
什么都没有

或者
是代码中分支的完美表示-它会朝一个方向或者另一个方向移动;
或者
。我们使用助记符来记住它:
是正确的方式;
是错误的方式(错误).这当然不是唯一的用途,但肯定是最常见的


我知道这些差异一开始可能看起来很微妙,但实际上它们适用于非常不同的事物。

好吧,你看,我们可以说,所有产品类型都可以用2元组表示,所有非递归和类型都可以用
表示。为了另外表示递归类型,我们需要一个不动点t类型

例如,当我们可以编写
(a,(b,(c,d))
((a,b,c),d)时,为什么有4元组
(a,b,c,d)

或者,为什么要列出清单,而下面的清单也适用

data Y f = Y (f (Y f))

type List a = Y ((,) (Either () a))


nil = Y (Left (), undefined)

cons a as = Y (Right a, as)

infixr 4 cons

numbers = 1 `cons` 2 `cons` 3 `cons` nil

-- this is like foldl

reduce f z (Y (Left (), _)) = z
reduce f z (Y (Right x, xs)) = reduce f (f z x) xs


total = reduce (+) 0 numbers

我很惊讶这不是一个骗局。好问题。提到逻辑析取,你得到了+1。对于FP新手来说,这是一个非常平易近人的答案。谢谢Jared。你的反馈对我来说意义重大^_^