2010-09-14 128 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)