4

我需要创建一个包含两个参数 anInt和 a的函数[Int],它返回一个 new[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是一种可比较的类型。但是,我不明白这一点,因为所有Ints 自然是可比的。如何使用这些参数解释和实现方法?我的意思是,开始的参数到底是什么?


@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]

才不是?


2013 年 2 月 7 日更新:对于所有可能在未来偶然发现这篇文章并提出相同问题的人,我在此链接上找到了一些关于 Haskell 的好信息,特别是我的问题:http://learnyouahaskell .com/types-and-typeclasses

“有趣。我们在这里看到了一个新的东西,=> 符号。=> 符号之前的所有内容都称为类约束。我们可以像这样阅读前面的类型声明:>equality 函数采用任意两个值相同类型并返回 Bool。这两个值的 >type 必须是 Eq 类的成员(这是类约束)。

Eq 类型类提供了一个用于测试相等性的接口。任何对测试该类型的两个值之间是否相等有意义的类型都应该是 Eq > 类的成员。除了 IO(处理输入和输出的类型)和函数之外的所有标准 Haskell 类型都是 Eq 类型类的一部分。”

4

2 回答 2

16

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

(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 的评论编辑)

于 2013-02-05T06:22:11.593 回答
6

您实现的(确切地说,您认为自己实现的)是一个仅适用于Integers 列表的函数,任务希望您做的是创建一个适用于所有类型列表的函数,前提是它们是相等可比的(这样您的函数也适用于布尔值或字符串列表)。您可能不必进行太多更改:尝试从代码中删除显式类型签名并询问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,类型签名应该匹配。

于 2013-02-05T04:55:35.670 回答