【问题标题】:Haskell: Non-strict boolean operationsHaskell:非严格的布尔运算
【发布时间】:2012-06-08 15:02:25
【问题描述】:

有没有在 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

我目前没有它的用​​例(尽管我对它感兴趣),我只是对它感兴趣。

【问题讨论】:

  • 这是惰性求值还是您对三值逻辑的 Haskell 解释?
  • undefined 不是一个值;这是没有价值。因此,不能“检查是否未定义”,只能选择:数字1、6、8或数字4、5、6;你不能两者兼得。

标签: haskell lazy-evaluation


【解决方案1】:

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

基本上,你写两个函数:

orL True _ = True
orL False x = x

orR = flip orL

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

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

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

【讨论】:

  • 为什么lub True False 是不确定的?直观地说,它应该返回undefined
  • @EarthEngine,因为这在定义顺序上不是单调的,因此不可能实现。特别是,f False 的定义不允许小于f undefined。如果你选择f = lub True,你就会得到你的榜样。
  • 那么有可能写lub' :: Bool -> Bool -> Maybe Bool这样lub' True False == Nothing吗?
  • 不,不可能,因为您仍然需要lub' True undefined = Just True,这与Nothing 无法比较(两者都是完全定义的,但值不同)。我显然不是解释这一点的最佳人选,我建议您提出一个单独的问题或转向文学。 “指称语义”和也许“领域理论”应该是很好的搜索查询起点。
【解决方案2】:

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

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

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

Prelude> or [True, undefined]
True

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

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

请记住,惰性值是带有幽灵的存在:

如果你往盒子里面看,可能会被鬼抓到。

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

【讨论】:

猜你喜欢
  • 2014-01-02
  • 2012-11-12
  • 2020-08-22
  • 2011-11-28
  • 2010-11-20
  • 2017-03-29
  • 2019-04-26
  • 1970-01-01
  • 2012-11-20
相关资源
最近更新 更多