저는 Haskell을 처음 접했고 이해할 수없는 “무한 유형을 구성 할 수 없습니다”라는 오류에 직면했습니다.
사실 그 이상으로이 오류가 무엇을 의미하는지에 대한 좋은 설명을 찾을 수 없었기 때문에 기본 질문을 넘어서 “무한 유형”오류에 대해 설명해 주시면 정말 감사하겠습니다.
코드는 다음과 같습니다.
intersperse :: a -> [[a]] -> [a]
-- intersperse '*' ["foo","bar","baz","quux"]
-- should produce the following:
-- "foo*bar*baz*quux"
-- intersperse -99 [ [1,2,3],[4,5,6],[7,8,9]]
-- should produce the following:
-- [1,2,3,-99,4,5,6,-99,7,8,9]
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:y:xs) = x:s:y:intersperse s xs
그리고 다음은 인터프리터에로드하려는 오류입니다.
Prelude> :load ./chapter.3.ending.real.world.haskell.exercises.hs
[1 of 1] Compiling Main (chapter.3.ending.real.world.haskell.exercises.hs, interpreted )
chapter.3.ending.real.world.haskell.exercises.hs:147:0:
Occurs check: cannot construct the infinite type: a = [a]
When generalising the type(s) for `intersperse'
Failed, modules loaded: none.
감사.
–
다음은 Haskell의 “무한 유형”오류를 처리하기위한 수정 된 코드와 일반적인 지침입니다.
수정 된 코드
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) = x ++ s:intersperse s xs
문제 :
내 타입 시그니처는 두 번째 매개 변수가 목록의 목록이라고 말한다. 따라서 “s (x : y : xs)”에 대해 패턴 매칭을했을 때 x와 y는 목록 이되었습니다 . 하지만 저는 x와 y를 목록이 아닌 요소로 취급했습니다.
“무한 유형”오류 처리 지침 :
대부분의 경우이 오류가 발생하면 다루고있는 다양한 변수의 유형을 잊어 버리고 변수가있는 것과 다른 유형 인 것처럼 사용하려고 시도한 것입니다. 모든 것이 어떤 유형인지, 어떻게 사용하는지주의 깊게 살펴보면 일반적으로 문제가 발견됩니다.
답변
문제는 마지막 절에 있습니다. 여기서 x와 y는 목록이지만 요소로 취급합니다. 이것은 작동합니다.
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs
무한 유형 오류는 : 연산자의 유형이 a-> [a]-> [a] 인 반면에 [a]-> a-> [a]로 취급하기 때문에 발생합니다. 즉, [a]는 a는 무한 중첩 목록임을 의미합니다. 그것은 허용되지 않습니다 (그리고 당신이 의미하는 바가 아닙니다).
편집 : 위 코드에는 또 다른 버그가 있습니다. 그것은해야한다:
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) = x ++ [s] ++ intersperse s xs
답변
종종 명시 적 유형 정의를 추가하면 컴파일러의 유형 오류 메시지가 더 의미가있을 수 있습니다. 그러나이 경우 명시 적 타이핑은 컴파일러의 오류 메시지를 더 악화시킵니다.
ghc가 intersperse의 유형을 추측하게하면 어떻게되는지보세요.
Occurs check: cannot construct the infinite type: a = [a]
Expected type: [a] -> [[a]] -> [[a]]
Inferred type: [a] -> [[a]] -> [a]
In the second argument of `(:)', namely `intersperse s xs'
In the second argument of `(:)', namely `y : intersperse s xs'
그것은 분명히 코드의 버그를 가리 킵니다. 이 기술을 사용하면 다른 사람들이 제안한 것처럼 모든 것을 쳐다보고 유형에 대해 열심히 생각할 필요가 없습니다.
답변
내가 틀렸을 수도 있지만 더 어려운 문제를 해결하려는 것 같습니다. 귀하의 버전은 intersperse
배열에 값을 산재 할뿐만 아니라 한 수준으로 평평하게 만듭니다.
List
Haskell 의 모듈은 실제로 intersperse 기능을 제공합니다. 목록의 모든 요소 사이에 주어진 값을 넣습니다 . 예를 들면 :
intersperse 11 [1, 3, 5, 7, 9] = [1, 11, 3, 11, 5, 11, 7, 11, 9]
intersperse "*" ["foo","bar","baz","quux"] = ["foo", "*", "bar", "*", "baz", "*", "quux"]
저는 이것이 제가 Haskell을 배우고있을 때 제 교수님이 우리가하기를 원했던 일이기 때문에 여러분이하고 싶은 일이라고 가정하고 있습니다. 물론 나는 완전히 나갈 수있다.