有人可以解释以下输出吗?
Prelude> compare True False
GT
it :: Ordering
Prelude> compare False True
LT
it :: Ordering
为什么在Haskell中排序Bool
类型的值 - 特别是,因为我们可以证明True和False的值不完全是1和0(与许多其他语言不同)?
答案 0 :(得分:8)
这是Ord
的派生实例的工作原理:
data D = A | B | C deriving Ord
鉴于该数据类型,我们得到C > B > A
。 Bool被定义为False | True
,当您查看其他示例时,它是有意义的,例如:
Maybe a = Nothing | Just a
Either a b = Left a | Right b
在每个案例中都有"某些" (" truthy")值大于根本没有值(或者"左"或"坏"或" falsy"值)
答案 1 :(得分:5)
虽然Bool
不是Int
,但它可以转换为0,1
的{{1}}片段,因为它是Int
类型。
Enum
现在,fromEnum False = 0
fromEnum True = 1
可能有所不同,正在推翻Enum
和0
,但对于大多数考虑比特的程序员而言,这可能会令人惊讶。
由于它具有1
类型,其他所有内容都相同,因此最好定义遵循相同顺序的Enum
实例,以满足
Ord
事实上,从compare x y = compare (fromEnum x) (fromEnum y)
生成的每个实例都遵循这样的属性。
从理论上讲,逻辑学家倾向于将命题从最强到最弱(形成一个格子)。在这种结构中,deriving (Eq, Ord, Enum)
(作为命题)是底部,即最小元素,而False
是顶部。虽然这只是一个惯例(如果我们选择相反的顺序,理论就会很好),但保持一致是件好事。
次要的缺点:暗示boolean connective实际上True
表示p <= q
暗示p
,而不是像“箭头”似乎表示的那样。
答案 2 :(得分:4)
让我回答一个问题:为什么Ord
有()
个实例?
与Bool
不同,()
只有一个可能的值:()
。那你为什么要比较它呢?只有一个值!
基本上,如果所有或大多数标准基本类型都具有公共类的实例,那么它很有用。它可以更轻松地为您自己的类型派生实例。如果Foo
没有Ord
个实例,并且您的新类型只有一个Foo
字段,则您无法自动派生Ord
实例
Tree x y z
这样的东西。您可能希望有一个Eq
实例来比较树。如果Tree () Int String
仅仅因为Eq
没有()
实例,那将会很烦人。这就是为什么()
有Eq
(和Ord
以及其他一些人)的原因。
类似的评论适用于Bool
。比较两个bool值可能听起来特别有用,但是如果你将Ord
实例放在那里就会消失,那将会很烦人。
(另一个复杂因素是有时候我们需要Ord
,因为这对事物有逻辑上有意义的排序,有时我们只想要一些任意顺序,通常我们可以使用某些东西作为Data.Map
或类似的关键字。可以说应该有两个单独的类......但是没有。)
答案 3 :(得分:0)
基本上,它来自数学。在集合论或类别理论中,布尔函数通常被认为是子集/子对象的分类器。简而言之,函数f :: a -> Bool
标识为filter f :: [a] -> [a]
。因此,如果我们将一个值从False
更改为True
,则生成的过滤列表(子集,子对象,等等)将具有更多元素。因此,True
被视为&#34;更大&#34;比False
。