如何解释(Eq a)

时间:2013-02-05 04:17:55

标签: haskell parameters typeclass

我需要创建一个包含Int[Int]两个参数的函数,它会返回一个新的[Int],并删除第一个参数的所有出现。

我可以轻松地创建函数,包括列表推导和列表递归。但是,我使用这些参数:

deleteAll_list_comp :: Integer -> [Integer] -> [Integer]
deleteAll_list_rec :: (Integer -> Bool) -> [Integer] -> [Integer]

但是,对于我的作业,我所需的参数是

deleteAll_list_comp :: (Eq a) => a -> [a] -> [a]
deleteAll_list_rec :: (Eq a) => a -> [a] -> [a]

我不知道如何阅读这种语法。正如谷歌告诉我的那样,(Eq a)只是向Haskell解释a是一种可比的类型。但是,我不明白这一点,因为所有Int都是自然可比的。如何使用这些参数解释和实现方法?我的意思是,开始的参数究竟是什么?


@groovy @pelotom

谢谢,这非常清楚。我现在明白,它实际上只需要两个参数而不是三个参数。但是,我仍然遇到此代码的问题。

deleteAll_list_rec :: (Eq a) => a -> [a] -> [a]
delete_list_rec toDelete [] = []
delete_list_rec toDelete (a:as) =
        if(toDelete == a) then delete_list_rec toDelete as
        else a:(delete_list_rec toDelete as)

这给了我一个“deleteAll_list_rec的类型签名   缺少一个附带的绑定“这对我来说没有意义,因为我是如何正确地绑定要求的,不是吗?从我的小经验来看,(a:as)在从中提取第一个元素时计为列表。为什么这会产生错误,但

deleteAll_list_comp :: (Eq a) => a -> [a] -> [a]
deleteAll_list_comp toDelete ls = [x | x <- ls, toDelete==x]

没有?


2/7/13更新:对于今后可能会遇到同样问题的所有人,我总体上找到了一些关于Haskell的好信息,我的问题具体来自这个链接:{{ 3}}

  

“有趣。我们在这里看到一个新的东西,=&gt;符号。=&gt;符号之前的所有内容都是&gt;称为类约束。我们可以读取前面的类型声明:&gt;相等函数需要任何两个相同类型的值并返回一个Bool。这两个值的&gt;类型必须是Eq类的成员(这是类约束)。

     

Eq类型类提供了一个用于测试相等性的接口。它使得&gt;感测测试该类型的两个值之间的相等性的任何类型都应该是Eq&gt;类的成员。除IO(处理输入和&gt;输出的类型)和函数之外的所有标准Haskell类型都是Eq类型类的一部分。“

2 个答案:

答案 0 :(得分:11)

考虑参数的一种方法可能是:

(Eq a) => a -> [a] -> [a]

(Eq a) =>   means any a's in the function parameters should be members of the 
            class Eq, which can be evaluated as equal or unequal.*

a -> [a]    means the function will have two parameters: (1) an element of
            type a, and (2) a list of elements of the same type a (we know that 
            type a in this case should be a member of class Eq, such as Num or 
            String).

-> [a]      means the function will return a list of elements of the same 
            type a; and the assignment states that this returned list should 
            exclude any elements that equal the first function parameter, 
            toDelete.

(*根据pelotom的评论编辑)

答案 1 :(得分:6)

你实现了什么(相反,你认为你实现了什么)是一个只适用于Integer列表的函数,作业要求你做的是创建一个适用于所有类型列表的函数是可比性的(这样你的函数也可以在布尔值或字符串列表上工作)。您可能不需要进行大量更改:尝试从代码中删除显式类型签名,并向ghci询问它将从您的代码中推断出的类型(:l yourfile.hs然后:t deleteAll_list_comp )。除非您使用算术运算或类似的东西,否则您很可能会发现您的函数已经适用于所有Eq a

作为一个更简单的例子,可以解释这个概念:假设我们想编写一个检查相等性的函数isequal(稍微没用,但是嘿):

isequal :: Integer -> Integer -> Bool
isequal a b = (a == b)

这是isequal的完美定义,但我手动设置的类型约束比它们更强。实际上,在没有手动类型签名的情况下,ghci推断:

Prelude> :t isequal
isequal :: Eq a => a -> a -> Bool

告诉我们该函数适用于所有输入类型,只要它们是deriving Eq,这意味着只需在它们上定义一个正确的==关系。


您的_rec功能仍然存在问题,因为它应该与您的_comp功能完全相同,因此类型签名应该匹配。