2014-05-21 2 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

이 문제는 당신이에 else if 문을 포함하지 않은 그것은 코드

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

의 이전 두 라인 사실이다, lookupAll하지입니다. 내 생각 엔 당신은 내가 개인적으로

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을 사용하는 것이지만 명시 적 재귀를 사용할 수도 있습니다.

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 

당신이 재귀를 사용하고자하는 경우로 filter를 사용하려면 함수를 작성할 수 대신

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 

이들 모두 동일로 작성할 수 있습니다. 사실, 당신은 희망이 filterlookupOne 사이의 유사성을 발견 할 수 filter

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

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

그리고 map

으로 구현할 수 있으며,이 둘의 합병 그래서 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

처음에는 "else"와 함께했지만 그 코드는 내가 원하는 코드가 아니 었습니다. 문제는 그것이해야 할 일을하지 않기 때문에 : 나는 "else"없이 그것을 필요로한다. xxx이면 xxx는 항상 yyy를 사용합니다. 무슨 뜻인지 알지? 그러나 당신 말이 맞습니다. "else undefined"를 사용하면 코드를 컴파일하여 오류가 발생하지 않습니다. – 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 (코블렌츠)], 코블렌츠 (코블렌츠)], 그리고 그 밖의 다른 사람들과 함께 거기에있다 : ### 실패한 부분 : LookupAll : 1 예상 : [ "코블렌츠" "Koblenz"] 하지만 : [ "코블렌츠"] .... 다른 언어에서는 당신은 그때만 쓸 수 있고 다른 사람에 대한 필요가 없습니다. 하지만 컴파일러가 나에게 오류가 발생하므로 여기에 else가 필요합니다. 그래서 나는 생각하는 모든 일을하지 않는 cmd가 필요합니다. 나는 첫 번째 가치를 지나치지 않고 있습니다. 나는 그것을 목록에 저장했다. 그 후 나는 recursiv 내 기능을 시작한다. – fuuman

1

내가 @bheklilr 잘 생각 - else이 누락되었습니다.

그러나 사용자 고유의 새로운 재귀 함수를 작성하는 대신 lookupOne을 함수 구성으로 형성하여이 특정 형식 문제를 해결할 수 있습니다.

예를 들어, 다음과 같이 lookupOne을 정의하여 행동의 오른쪽 종류를 얻을 수 있습니다 :

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

가 먼저 입력리스트의 요소를 필터링하고 있는지 명확의이 방법을하는 첫 번째 요소에 대한 튜플의 두 번째 요소를 추출한 다음 각 튜플의 두 번째 요소 만 추출합니다.