간단한 코드 조각을 컴파일하려고합니다.
main = (putStrLn . show) (Right 3.423)
컴파일 결과 다음 오류가 발생합니다.
No instance for (Show a0) arising from a use of `show'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 42 others
In the second argument of `(.)', namely `show'
In the expression: putStrLn . show
In the expression: (putStrLn . show) (Right 3.423)
ghci에서 동일한 스 니펫을 실행하면 모든 것이 예상대로 작동합니다.
Prelude> let main = (putStrLn . show) (Right 3.423)
Prelude> main
Right 3.423
그래서 문제는 무슨 일이 일어나고 있는가?
문제는 GHC이의 모든 유형을 결정 할 수 없다는 것입니다 Right 3.423
IS, 그것은 단지 그것을 유형이 있음을 확인할 수 있습니다 Either a Double
, 그리고 인스턴스 Show
에 대한 Either
같은 모습을 instance (Show a, Show b) => Show (Either a b)
. 에 대한 추가 제약이 없으면 Either a Double
GHC는 인쇄 방법을 모릅니다.
이 대화 형 모드에서 작동하는 이유는 때문이다 무서워 단사 사상의 제한 이 선택 기본값에 GHCi 더 공격적으로합니다. 이 기능은으로 비활성화 할 수 있으며 :set -XNoMonomorphismRestriction
초보자에게 많은 문제가 발생하므로 향후 GHC 버전에서 기본값이 될 것입니다.
이 문제에 대한 해결책은 다음 Right 3.423
과 같이 소스 코드 에 유형 서명을 넣는 것입니다.
main = (putStrLn . show) (Right 3.423 :: Either () Double)
우리는 어쨌든 그것에 대해 신경 쓰지 않고 보여줄 수있는 "가장 단순한"유형이기 때문에 여기서 방금 사용 ()
했습니다 a
. 구현하는 한 String
또는 Int
또는 Double
또는 원하는 것을 거기에 넣을 수 Show
있습니다.
팁 putStrLn . show
은 정확히의 정의 print
이므로 할 수 있습니다.
main = print (Right 3.423 :: Either () Double)
@ ØrjanJohansen이 지적했듯이 이것은 단 형성 제한이 아니라 ExtendedDefaultRules
GHCi가 사용 하는 확장입니다. 기본적으로 위에서 한 작업을 정확히 ()
수행하고 대화 형 세션에서 작업을 수행하기 위해 유형 변수를 밀어 넣 습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다