2014-05-21 93 views
0

我在哈斯克爾編程初學者,很多時候我得到的錯誤哈斯克爾 - 格式問題

xxx.hs:30:1: parse error on input `xxx' 

而且經常有一點點的格式解播放。它的代碼和它看起來一樣,但玩過之後,錯誤消失了。

此刻,我已經得到了錯誤

LookupAll.hs:30:1: parse error on input `lookupAll' 

代碼後:

lookupOne :: Int -> [(Int,a)] -> [a] 
lookupOne _ [] = [] 
lookupOne x list = 
    if fst(head list) == x then snd(head list) : [] 
    lookupOne x (tail list) 
-- | Given a list of keys and a list of pairs of key and value 
-- 'lookupAll' looks up the list of associated values for each key 
-- and concatenates the results. 

lookupAll :: [Int] -> [(Int,a)] -> [a] 
lookupAll [] _ = [] 
lookupAll _ [] = [] 
lookupAll xs list = lookupOne h list ++ lookupAll t list  
    where 
     h = head xs 
     t = tail xs 

但我就在我的意見所做的一切。沒有標籤或類似的東西。總是4個空格。這個問題是否有一個通用的解決方案?我現在使用記事本++。

謝謝!

+2

您忘記了'else'子句不是Haskell中'if'表達式的可選部分。 –

回答

4

的問題不在於lookupAll,它實際上是用代碼

if fst (head list) == x then snd (head list) : [] 
lookupOne x (tail list) 

了前兩行您還沒有if語句在這一個else。我的猜測是,你的意思是

if fst (head list) == x then snd (head list) : [] 
else lookupOne x (tail list) 

,我個人更願意爲

if fst (head list) == x 
    then snd (head list) : [] 
    else lookupOne x (tail list) 

格式化但這是口味的問題。


如果您想要累積符合條件的值列表,有幾種方法。目前最簡單的方法是使用filter,但也可以使用顯式遞歸。要使用filter,你可以寫你的函數作爲

lookupOne x list 
    = map snd       -- Return only the values from the assoc list 
    $ filter (\y -> fst y == x) list -- Find each pair whose first element equals x 

如果你想使用遞歸,你可以代替它寫成

lookupOne _ [] = []     -- The base case pattern 
lookupOne x (y:ys) =     -- Pattern match with (:), don't have to use head and tail 
    if fst y == x     -- Check if the key and lookup value match 
     then snd y : lookupOne x ys -- If so, prepend it onto the result of looking up the rest of the list 
     else   lookupOne x ys -- Otherwise, just return the result of looking up the rest of the list 

這兩個是等價的。事實上,你可以實現filter作爲

filter cond [] = [] 
filter cond (x:xs) = 
    if cond x 
     then x : filter cond xs 
     else  filter cond xs 

而且map作爲

map f [] = [] 
map f (x:xs) = f x : map f xs 

希望你能發現filterlookupOne之間的相似性,並與map考慮f == snd,讓您擁有兩者的合併mapfilter的模式在lookupOne的顯式遞歸版本中。你可以概括這個組合圖案爲一個高階函數

mapFilter :: (a -> b) -> (a -> Bool) -> [a] -> [b] 
mapFilter f cond [] = [] 
mapFilter f cond (x:xs) = 
    if cond x 
     then f x : mapFilter f cond xs 
     else  : mapFilter f cond xs 

,你可以用它來實現lookupOne作爲

lookupOne x list = mapFilter snd (\y -> fst y == x) list 

或者更簡單地說

lookupOne x = mapFilter snd ((== x) . fst) 
+0

首先我把它與「其他」,但那不是我想要的代碼。因爲問題並沒有做它必須做的事情:D我需要它沒有「其他」。如果xxx然後xxx並且總是yyy。你知道我的意思?但你是對的。使用「其他未定義」,編譯代碼不會出錯。 – fuuman

+0

@fuuman你想積累一個值的列表返回?如果是這樣,這不是做到這一點的方法。在Haskell中,計算一個值是沒有意義的('snd(head list):[]'),然後把這個值扔掉並計算另一個值('lookupOne x(tail list)')。所有表達式都會返回一個值,並且該值必須是靜態類型。 – bheklilr

+0

這就是代碼應該做的事:lookupAll [1,2] [(1,「Koblenz」),(1,「Koblenz」)]〜?= [「Koblenz」,「Koblenz」], lookupAll [1,1 ] [(1,「科布倫茨」)]〜?= [「科布倫茨」,「科布倫茨」],並與之前查找一個有:###失敗:查找所有:1 預計:[「科布倫茨」, 「科布倫茨」] 但得到了:[「科布倫茨」] ....在其他語言中,你只能寫,如果沒有其他的需要。但編譯器給我一個錯誤,所以我需要這裏的其他東西。所以我需要一個cmd,它不會做我認爲的任何事情......我沒有完成第一個價值。我保存在列表中。之後,我recursiv開始我的功能 – fuuman

1

我覺得@bheklilr是正確的 - 你錯過了else

但是,通過將lookupOne作爲函數組合形成,而不是編寫自己的新遞歸函數,可以修復此特定格式問題。

例如,您可以通過定義lookupOne這樣得到正確的一種行爲:

lookupOne a = map snd . filter ((==) a . fst) 

這種方式是清晰的,你先過濾掉輸入列表中的元素,其第一要素的元組匹配鍵,然後提取每個元組的第二個元素。