我认为您将类型 ( [(a,b)]
) 与模式混淆了。在你的isEmpty
函数中,你写:
isEmpty::Ord a => [(a,b)] -> Bool
isEmpty [(a,b)] = null [undefined, undefined]
但这并不意味着您要匹配type [(a,b)]
的列表。你已经在你的类型签名中说过了。你[(a,b)]
在第二行,意味着你定义了一个模式。该模式说您只匹配包含一个元素的列表:一个 2 元组,a
该元组的第一项,该元组b
的第二项。
如果您随后将一个空列表或包含两个或多个元素的列表传递给它,则该模式将不匹配,因此会引发错误。
如果你想匹配任何列表,你可以简单地使用一个变量:
isEmpty :: Ord a => [(a,b)] -> Bool
isEmpty ls = null ls
因此,这里isEmpty
将null
使用该变量调用。我们可以在这里执行η-reduction,并写成:
isEmpty :: Ord a => [(a,b)] -> Bool
isEmpty = null
完全没有必要将自己限制为仅具有 2 元组的列表,其中这些元组的第一项具有类型类成员的Ord
类型,但是,我们可以让它与任何列表一起使用。所以我们可以将类型概括为:
isEmpty :: [a] -> Bool
isEmpty = null
事实上null
可以操作任何Foldable
,因为它有类型null :: Foldable f => f a -> Bool
。
有了上面的函数定义,就不需要自己实现了isEmpty
,直接调用就可以了null emptyList
。