7

无论如何在Haskell中定义如下函数?

or True      True      = True
or True      undefined = True
or True      False     = True
or undefined True      = True
or undefined False     = undefined
or undefined undefined = undefined
or False     True      = True
or False     undefined = undefined
or False     False     = False

我目前没有它的用​​例(尽管我会对它感兴趣),如果可能的话,我只是感兴趣。

4

2 回答 2

15

这在标准 Haskell 中是不可能的,但可以通过 Conal Elliott在lub库中实现的不安全技巧来完成。

基本上,您编写两个函数:

orL True _ = True
orL False x = x

orR = flip orL

然后您可以定义or a b为 and 的(lub关于“定义”顺序的最小上限)。orL a borR a b

在操作上,它并行运行两个计算并选择第一个成功的,杀死另一个。

即使按照您的建议工作,它也有重要的缺点。首先,lub只有当它的论点一致时才安全(除非底部相等)。如果你取lub True False,结果将是不确定的,从而违反了纯洁性!其次,在某些情况下,并行运行这两种计算的性能开销可能会变得很重要(foldr or False例如,尝试计算一个大列表的 a !)。

于 2012-06-08T15:36:57.747 回答
12

根据您的评估顺序(检查值的顺序),您可以编写一个惰性版本:

Prelude> True || undefined
True
Prelude> undefined || True
*** Exception: Prelude.undefined

Prelude> :t or
or :: [Bool] -> Bool

Prelude> or [True, undefined]
True

事实上,Haskell 中的默认定义会表现得像这样,因为 Haskell 是一种惰性语言。

但是,如果不先查看该值,就无法“跳过”未定义的值,这会将其评估为底部,这会导致您的表达式未定义。

请记住,惰性值是其中包含幽灵的礼物:

在此处输入图像描述

如果你看看盒子里面,鬼可能会抓住你。

如果检查底部很重要(例如,作为测试套件的一部分),您可以将它们视为异常,并拦截它们。但是你不会在纯函数中这样做。

于 2012-06-08T15:06:25.177 回答