2014-05-14 5 views
0

난 하스켈 다음의 두 가지 기능을 가지고 있으므로해석 에러 : XS - 이해

plusList :: [[Int]] -> [Int] 
plusList [xs ys] = add xs + plusList [ys] 
plusList [[]] = 0 


add::[Int] -> Int 
add (x:xs) = x + add xs 
add [] = 0 

, 난 XS + plusList YS를 난 plusList [XS의 YS]의 오류가 있다고 생각 = 추가

제 아이디어는 [[Int]] 세트를 살펴보고 첫 번째 List xs를 가져 와서 "add"를 적용한 다음 두 번째리스트 ys를 "plusList ys"와 재귀 적으로 호출하는 것입니다.

저는 haskell을 처음 접했습니까? 그리고 만약 아니라면, 왜?

답변

10

하스켈에서 원하는대로 할 수는 있지만 구문이 잘못되었습니다. add 함수는 정확하지만 plusList은 올바르지 않습니다. 특히, 구문 [xs ys] 당신은 아마이 정확히 add와 동일 패턴이 얼마나

plusList (xs:ys) = add xs + plusList ys 

공지 사항을 원 하스켈에 패턴으로 이해되지 않는다? 형식 서명에서 정확히 원하는 것을 말하기는 어렵습니다. 형식에 Int의 목록이 반환되지만 기능 본문에는 Int 만 반환된다고되어 있습니다. 전자를 원할 경우

plusList (xs:ys) = add xs : plusList ys 

으로 달성 할 수 있습니다.하지만 정확히 map add입니다. 대신 후자를 원한다면 위의 첫 번째 스 니펫을 사용하십시오.

당신이 두 번째 문제는이 하스켈 코드를 완벽하게 유효하고 법적 라인이지만, 당신이 원하는 것을하지 않을 것이다

plusList [[]] = 0 

입니다. 알다시피, [] :: [[Int]][[]] :: [[Int]] 사이에 차이가 있습니다. 첫 번째는 Int s의 빈 목록이고 두 번째는 Int s의 빈 목록을 포함하는 목록입니다. length ([] :: [[Int]])을 실행하면 0이 표시되지만 length ([[]] :: [[Int]])은 1이됩니다. 대신, 그냥 do

plusList [] = 0 

add의 패턴과 같습니다. 대신 [Int]을 반환 plusList를 원하는 경우,이 라인은 단지 우리가

plusList :: [[Int]] -> [Int] 
plusList (xs:ys) = add xs : plusList ys 
plusList [] = [] 
-- or just 
-- plusList xs = map add xs 

쉽게

plusList :: [[Int]] -> Int 
plusList (xs:ys) = add xs + plusList ys 
plusList [] = 0 

그리고

되어 있습니다 그래서 두 버전

plusList [] = [] 

해야한다 그래도 할 수있는 방법. 첫째, add은 내장 된 sum 함수에 불과하지만 Int에 특화되어 있습니다. 그러나 내장형 sumfoldl을 사용하기 때문에 효율성이 떨어집니다.이 함수형 프로그래밍에서 같은 일반적인 패턴이기 때문에 대신에, 당신은 foldrfoldl 함수를 사용하면 사용한 재귀의 종류를 일반화

add :: [Int] -> [Int] 
add xs = foldr (+) 0 xs 

와 빠른 변형을 구현할 수 있습니다. 전체 목록을 조작하는 대신 다음 값과 누적기를 함께 결합하는 함수, 초기 누적 값 및 누적 값을 제공합니다. 귀하의 경우 누산기는 값과 동일한 유형을 가지며, 이는 일반적입니다. foldlfoldr의 차이점은 미묘합니다. 구현은 꽤 비슷해 보이지만, 하스켈의 게으름은 foldl이 공간 누출과 효율성 문제를 가질 수 있음을 의미합니다. 왜 거기에 도달했는지 자세히 설명해줍니다. 당신이 목록의 목록을 요약하려는 경우

또한, 당신이 필요한 추가 단순히

plusList = add . map add 

아무것도 고차 함수를 사용하여 수행 할 수없는 패턴이 잘못되기 훨씬 적은 구문과 일치 없습니다.

+0

'foldr'과 'foldl'을 섞어서 사용한다고 생각합니다. 여기에'foldr'은 공간 누설을 가지고 있지만, 썽크가 아닌 스택 공간 (썽크가 실행되면 스택이 뒤 따른다.)이 있다고 생각한다. –