我认为您将类型 ( [(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。