在使用Haskell列表时,为什么要在t -> [t] -> [t]的签名中包含(Eq t)?

omhiaaxx  于 2023-05-29  发布在  其他
关注(0)|答案(2)|浏览(169)

我正在处理使用t类型元素列表的函数。这意味着列表可以是整数列表,也可以是字符串或字符列表。但是我不明白为什么(Eq t)必须在类型签名中。
举个例子

belong :: (Eq t) => t -> [t] -> Bool    
belong e [] = False
belong e (x:xs) | e == x = True
                | otherwise = belong e xs

--为什么(等式t)在签名中?

tpgth1q7

tpgth1q71#

将列表元素x与项ee == x进行比较。这是一个测试这两个t类型的项是否相等的操作。要做到这一点,项目本身必须是可比较的,因为你不能只是比较两个任意的东西。你的函数在t类型中是 * 参数多态的 *,t是一个无约束的类型变量,所以类型可以是任何东西,一般来说不可能推理出该类型上可能的态射。
函数签名中的类约束(Eq t) =>告诉类型t应该属于类型类Eq。它 * 表达了一个要求 *,即列表中的项目和你要比较的项目必须是可比较的。

class Eq a where
  (==) :: a -> a -> Bool
   ...

类型类Eq定义了具有a -> a -> Bool类型的函数==,它就像一个“接口”,所有实现这个类型类的类型都将拥有它。
==函数的确切实现将根据t所用具体类型的Eq类型类的 * 示例 * 来确定;这是一个特殊多态性的例子,其中每个具体值都采用一个类型类,因为它已经被赋予了这个类型类的单独定义。

9udxz4iz

9udxz4iz2#

在“guard"中,您可以写入e == x。现在,为了检查两个项是否相等,我们使用(==) :: Eq a => a -> a -> Bool。并不是每个类型都可以使用这个函数,正如类型签名已经说过的那样,需要将该类型作为Eq类型类的示例,以定义两个项是否相等。
然而,该函数可以简化为:

belong :: Eq t => t -> [t] -> Bool
belong e [] = False
belong e (x:xs) = e == x || belong e xs

或使用any在任何Foldable上工作:

belong :: (Eq t, Foldable f) => t -> f t -> Bool    
belong = any . (==)

由于base-4.8,您的函数已经在Prelude中存在此泛型签名:elem :: (Eq a, Foldable f) => a -> f a -> Bool

相关问题