2010-09-14 61 views
2

好,所以我们还没有学习多态函数,但我们仍然需要编写这段代码。Haskell:递归与多态相等函数

Given: 
nameEQ (a,_) (b,_) = a == b 
numberEQ (_,a) (_,b) = a == b 
intEQ a b = a == b 
member :: (a -> a -> Bool) -> a -> [a] -> Bool 

我说:

member eq x ys | length ys < 1 = False 
       | head(ys) == x = True 
      | otherwise = member(x,tail(ys)) 

,但我得到有关不正确的类型,以及一些其他的东西的错误。我们必须从某种类型看看是否存在一个元素。所以我们有以上两种类型。一些例子给出:

phoneDB = [("Jenny","867-5309"), ("Alice","555-1212"), ("Bob","621-6613")] 

> member nameEQ ("Alice","") phoneDB 
True 
> member nameEQ ("Jenny","") phoneDB 
True 
> member nameEQ ("Erica","") phoneDB 
False 
> member numberEQ ("","867-5309") phoneDB 
True 
> member numberEQ ("","111-2222") phoneDB 
False 
> member intEQ 4 [1,2,3,4] 
True 
> member intEQ 4 [1,2,3,5] 
False 

不完全知道我需要在这里做。任何关于此的帮助或文档都会很棒。谢谢!

回答

5

你掩饰的那些错误“关于不是正确的类型以及其他一些东西”很重要。他们告诉你什么是错的。

例如,第一次我把你的代码ghc我:

Couldn't match expected type `a -> a -> Bool' 
     against inferred type `(a1, [a1])' 
In the first argument of `member', namely `(x, tail (ys))' 
In the expression: member (x, tail (ys)) 
In the definition of `member': 
    member eq x ys 
      | length ys < 1 = False 
      | head (ys) == x = True 
      | otherwise = member (x, tail (ys)) 

好吧,当我看着它那简单 - 你输入

member(x,tail(ys)) 

当你清楚意思是:

member x (tail ys) 

逗号意味着你不打算在那里的Haskell。

一旦我做了这个改变,它再次抱怨说你忘了eq参数member

之后的错误更加困难,如果您还没有了解Haskell类型类,但可以说您需要使用传入的eq函数进行比较,而不是使用==

+0

好的,我不知道eq功能。是的,我认为我有这一点,我不断收到错误(可能是由于==)。谢谢你的帮助。 – Matt 2010-09-14 11:46:14

+1

@Matt:'eq'不是你不知道的库函数 - 它作为参数传递给你写的'member'函数! – 2010-09-15 18:48:09

7

各种各样的东西(我不会写出完整的答案,因为这是家庭作业):

  1. length ys < 1可以更简单地表示为null ys
  2. 你并不需要大约函数参数括号。 head(ys)更通常写成head ys
  3. 如果您愿意,可以将顶部案例和其他两个案件转换为模式匹配而非警卫。 member eq x [] = ...将匹配空案例,member eq x (y:ys) = ...将匹配非空案例。
  4. 您正在使用==进行比较。但是你打算使用eq函数来代替。
  5. 您正在将成员的参数括起来,就好像这是Java或类似的。在Haskell中,参数用空格分隔,所以member(x,(tail(ys))应该是member x (tail ys)
+2

For第二点:不仅是那些不必要的东西,他们实际上会欺骗你相信东西是按照它不是这样的方式分组的;例如,'foo a b(c)'用三个参数调用'foo',而不是两个。你可能的意思是'foo a(b c)' – 2010-09-14 11:11:37

+0

是的,我们不得不使用我们给的东西。所以成员公式x(y:ys)是不可能的。但无效的是有帮助的。谢谢。这确实有帮助。 – Matt 2010-09-14 11:47:18

2

由于参数amember :: (a -> a -> Bool) -> a -> [a] -> Bool 没有得到Eq,您不能使用==对它们进行比较, 而是必须使用特定的函数eq

因此你的代码可能是这样的:

member :: (a -> a -> Bool) -> a -> [a] -> Bool 
member eq x ys 
| length ys < 1 = False 
| eq x (head ys) = True 
| otherwise = member eq x (tail ys) 

与此唯一的问题是,该长度仍然需要评估整个列表, 所以你可以达到AA更好的性能写作:

member' :: (a -> a -> Bool) -> a -> [a] -> Bool 
member' eq x (y:ys) 
| eq x y = True 
| otherwise = member' eq x ys 
member' _ _ [] = False 

使用任何你可以更简化它:

member'' :: (a -> a -> Bool) -> a -> [a] -> Bool 
member'' f a = any (f a)