2014-01-22 3 views
4

나는 foldl 튜플 목록을 통해 이동하여 문자열을 만드는 데 사용하는 함수를 얻으려고하고 있어요. 이미 재귀를 사용하여 작동하는 비슷한 함수를 만들려고합니다. 여기 Haskell 재귀 foldl처럼 사용

내가 컴파일하기 위해 노력하고있어 코드입니다 : 제공된 코드의 맨 마지막 줄에 따라서

citeBook :: (String, String, Integer) -> String 
citeBook (name, titl, date) = (titl ++ " (" ++ name ++ ", " ++ show date ++ ")\n") 

--Recursion function 
-- function must be called with putStr in order for newlines to work 
bibliography_rec :: [(String, String, Integer)] -> String 
bibliography_rec [] = "" 
bibliography_rec xs = (citeBook(head xs) ++ bibliography_rec (tail xs)) 

--foldl function 
bibliography_fold :: [(String, String, Integer)] -> String 
bibliography_fold [] = "" 
bibliography_fold (x:xs) = foldl (++) citeBook(x) xs --ERROR HERE 

, 나는 foldl 사용을 위해 노력하고 있어요 (++) 연산자와 같이 목록에있는 문자열을 조합하십시오. x가 목록에서 가져온 첫 번째 튜플 이 될 것이므로 기본 사례로 citeBook (x)을 사용하고 있습니다. citeBook (x)은 문자열을 반환합니다. 그런 다음 목록 xs와 함께 접기를 계속하십시오.

여기에 오류가 있습니다. 나는 foldl 내 매개 변수 유형이 아닌 예상 무슨와 일치 생각하지만, 모든

hw1.hs:28:34: 
    Couldn't match type `[a0]' 
        with `(String, String, Integer) -> String' 
    Expected type: ((String, String, Integer) -> String) 
        -> [a0] -> (String, String, Integer) -> String 
     Actual type: [a0] -> [a0] -> [a0] 
    In the first argument of `foldl', namely `(++)' 
    In the expression: foldl (++) citeBook (x) xs 
    In an equation for `bibliography_fold': 
     bibliography_fold (x : xs) = foldl (++) citeBook (x) xs 

hw1.hs:28:48: 
    Couldn't match expected type `[[a0]]' 
       with actual type `(String, String, Integer)' 
    In the third argument of `foldl', namely `(x)' 
    In the expression: foldl (++) citeBook (x) xs 
    In an equation for `bibliography_fold': 
     bibliography_fold (x : xs) = foldl (++) citeBook (x) xs 

hw1.hs:28:51: 
    Couldn't match expected type `(String, String, Integer)' 
       with actual type `[(String, String, Integer)]' 
    In the fourth argument of `foldl', namely `xs' 
    In the expression: foldl (++) citeBook (x) xs 
    In an equation for `bibliography_fold': 
     bibliography_fold (x : xs) = foldl (++) citeBook (x) xs 

내가 어떤 모든 의견을 보내 주셔서 감사합니다 .. 나에게 좋아 보인다. 감사!

+2

'bibliography_rec'는'concatMap citeBook'이 아니십니까? – bheklilr

+0

예, 답변으로 게시하십시오. – amnn

+0

bheklilr, 방금 해보았지만 작동하지만 명시 적으로 재귀 함수를 만들려고했습니다.내 문제는 내가 bibliography_rec 같은 목록을 인쇄하려고하지만 재귀 대신 foldl 사용 –

답변

4

유형의 (++) 기능을 제공했습니다. 그러나 접히는 컬렉션 인 xs[(String, String, Integer)] 유형이고 [String] 유형은 아닙니다.

당신은 bibliography_fold

bibliography_fold :: [(String, String, Integer)] -> String 
bibliography_fold [] = "" 
bibliography_fold (x:xs) = foldl (++) (citeBook x) (map citeBook xs) 

에하거나

bibliography_fold :: [(String, String, Integer)] -> String 
bibliography_fold xs = foldl (++) "" (map citeBook xs) 

에 변경 될 수 있지만 자신이 그렇게 에누리 내 코딩 스타일을 하스켈에서 상대 멍청한 놈입니다.

또한, 당신은 (citeBook x)하지 citeBook(x)를 작성해야하거나, 컴파일러는 citeBook(x)foldl에 두 인수가 (내가 틀렸다면 정정 해줘) 있다고 가정합니다. 이것은 당신이 가진 오류 메시지가 왜 이상하게 보이는지 설명하는 데 도움이됩니다.

+0

필자는'foldl (++) ""버전이 빈 목록을 특수하게 만들지 않으므로 훨씬 더 바람직하다고 강조했습니다. – hugomg

+0

감사합니다 jcarpenter! 그것은 아주 잘 해결되었습니다. 나는 하스켈 자신의 멍청 아. 나는지도 함수에 익숙하지 않다. 나는 약간의 연구를하고있는 것처럼 보입니다. –

+0

지도 함수없이 다음과 같이 작성할 수도 있습니다 :'bibliography_fold xs = foldl (\ s t -> s ++ citeBook t) '' "xs'. 이제 accumulator 함수는'String -> (String, String, Integer) -> String' 타입을 가지며'[(String, String, Integer)]를 다시 접습니다. – jcarpenter2

3

이미 답변을받은, 그래서 나는이 문제를 해결하기 위해 배를 사용하는 또 다른 방법 제공합니다 :

bibliography_fold :: [(String, String, Integer)] -> String 
bibliography_fold = foldr ((++) . citeBook) "" 

더지도, 특별한 경우가 없다, 그리고이 지점에서 쓸 수 있습니다 무료 스타일. GHCi에서이 표현식을 해체하고 :info을 사용하여 각 구성 요소를 검사하여 실제로 작동하는 방식을 탐색하는 것이 좋습니다. foldr, ++, citeBook, (++) . citeBook의 유형을 살펴보고 이것이 작동하는 이유를 알아보세요. foldr의 소스 코드를 찾아 볼 수도 있습니다.

+0

+1 foldl 대신 foldr을 사용하는 것이 좋습니다. – kosmikus