Haskell中isNothing和(=Nothing)之间的区别?
我不明白为什么下面两个不涉及任何内容的函数是不同的:Haskell中isNothing和(=Nothing)之间的区别?,haskell,maybe,Haskell,Maybe,我不明白为什么下面两个不涉及任何内容的函数是不同的: coalesce m1 m2 = if isNothing m1 then m2 else m1 coalesce' m1 m2 = if (m1 == Nothing) then m2 else m1 第一种类型为: λ> :t coalesce coalesce :: Maybe a -> Maybe a -> Maybe a 正如所料。但第二个问题是: λ> :t coalesce' coalesce
coalesce m1 m2 = if isNothing m1 then m2 else m1
coalesce' m1 m2 = if (m1 == Nothing) then m2 else m1
第一种类型为:
λ> :t coalesce
coalesce :: Maybe a -> Maybe a -> Maybe a
正如所料。但第二个问题是:
λ> :t coalesce'
coalesce' :: Eq a => Maybe a -> Maybe a -> Maybe a
为什么使用(==Nothing)
会引入Eq a
约束
(GHC 8.2.2)因为
=
的类型是
(==) :: (Eq a) => a -> a -> Bool
第二个定义(coalesce'
)使用=
,因此它继承了=
对其参数的Eq
约束
严格来说,
coalesce'
对类型为的值使用=
,可能是a
,但有一个实例
instance (Eq a) => Eq (Maybe a) where ...
因此,
Eq(可能是a)
约束变成了Eq a
,因为这是在上支持=
所需要的,可能a
=
是一个函数Eq a=>a->Bool
。您正在使它的一个操作数Nothing
,因此a
对于某些类型b
是可能b
,但是Eq a
限制仍然适用–可能b
必须有一个Eq
实例Maybe b
包括这样一个实例的定义–Eq(Maybe b)
–用于所有Eq b
换句话说,==
只是一个函数,它事先不知道您正在提供什么也不提供
作为参数。它只知道它是某个可能是一个,如果它恰好是一个只是…
,它需要能够比较相等
换句话说,这里是如何定义已经存在于的==
,可能是的:
equals a b = case a of
Nothing -> isNothing b
Just x -> case b of
Nothing -> False
Just y -> x == y
注意x==y
是如何出现的,这意味着x
和y
类型必须有一个Eq
实例,让我们首先设计一个(==)
函数覆盖值。通常,如果两个事物具有相同的数据构造函数,并且参数都是相等的,则我们认为两个事物是相同的。因此,我们考虑<代码> f x1 x2 x3和<代码> g y1 y2 y3 < /c> >相同,如果<代码> f>代码>和<代码> g>代码>是相同的数据构造函数,并且<代码> x1==y1 ,<代码> x2==y2< /代码>,和<代码> x3==y3 < /p>
因此,如果我们为Maybe
实现这一点,则有两种情况是相等的:两个Nothing
s和两个Just
s,其中Just
s封装的值相同,因此:
instance Eq a => Eq (Maybe a) where
(==) Nothing Nothing = True
(==) (Just x) (Just y) = x == y
(==) _ _ = False
是实现Eq
实例的最合乎逻辑的方法,例如可能是a
。在实现中,我们使用x==y
,因此我们添加了Eq a
类型约束
现在Haskell将函数概念上看作是黑盒。对于Maybe
,它因此将(==)
视为(==)::Eq a=>Maybe a->Maybe a->Bool
。如果因此使用此(==)
函数,则无论特定用途是否需要此类型约束来执行x==y
检查,它都将始终需要类型约束Eq a
。如果您编写(==Nothing)
,那么我们会看到,第二个子句((==)(仅x)(仅y)
)将永远不会被使用,但是由于Haskell将函数视为黑盒,因此不知道在什么情况下类型约束是相关的
仅检查值是否为Nothing
,如果它是Just
,则它始终为False
,无论Just
构造函数包装的值是什么,它的实现方式如下:
isNothing :: Maybe a -> Bool
isNothing Nothing = True
isNothing _ = False
因此,我们不需要这里的Eq a
类型约束:我们不检查元素的相等性,只检查构造函数的换行。同样,如果我们使用它,Haskell只检查类型签名,注意到不涉及Eq a
类型约束,因此不会将其添加到使用该函数的函数中
请注意,您在此处实现的实际上已经在控件.Applicative
模块中实现,例如:
Prelude> import Control.Applicative
Prelude Control.Applicative> (<|>) Nothing Nothing
Nothing
Prelude Control.Applicative> (<|>) Nothing (Just 3)
Just 3
Prelude Control.Applicative> (<|>) (Just 3) Nothing
Just 3
Prelude Control.Applicative> (<|>) (Just 3) (Just 2)
Just 3
Prelude>导入控制。应用程序
前奏曲控件。应用>()无
没有什么
前奏曲控件。应用>()无(仅3)
只有3个
前奏曲控件。应用程序>()(仅3)无
只有3个
前奏曲控件.Applicative>()(仅3)(仅2)
只有3个
可能值得明确指出的是,这种差异是非常重要的:有些东西(通常是函数)不能有Eq
实例。所以coalesce
可以很好地处理这些问题,但是coalesce'
不行。