2014-09-18 4 views
3

추론 된 유형 서명이 내가 기대했던 것과 다른 이유를 이해하는 데 약간의 어려움이 있습니다.유추 추세 유형

import Control.Applicative 
import Data.Word 
import Text.ParserCombinators.Parsec 
import Text.ParserCombinators.Parsec.Token 
import Text.Parsec.Language (emptyDef) 
import Text.Parsec.Prim 
import Data.Functor.Identity 

--parseUInt' :: Num b => ParsecT String u Identity b 
parseUInt' = fromInteger <$> decimal (makeTokenParser emptyDef) 
--parseUInt1 = fromInteger <$> decimal (makeTokenParser emptyDef) 
--parseUInt2 = fromInteger <$> decimal (makeTokenParser emptyDef) 

parsePairOfInts = do 
    x <- parseUInt' 
    char ',' 
    y <- parseUInt' 
    return $ (x, y) 

parseLine :: String -> Either ParseError (Word32, Word8) 
parseLine = parse parsePairOfInts "(error)" 

main = print . show $ parseLine "1,2" 

이 코드는 컴파일되지 않습니다 :

test.hs:21:19: 
    Couldn't match type ‘Word32’ with ‘Word8’ 
    Expected type: Parsec String() (Word32, Word8) 
     Actual type: ParsecT String() Identity (Word32, Word32) 
    In the first argument of ‘parse’, namely ‘parsePairOfInts’ 
    In the expression: parse parsePairOfInts "(error)" 
Failed, modules loaded: none. 

을하지만 parseUInt'의 유형 서명의 주석을 경우는 잘 컴파일의 예로 들어 보자 (I는 가능한 한 짧게 만들려고).

λ>:t (fromInteger <$> decimal (makeTokenParser emptyDef)) 
(fromInteger <$> decimal (makeTokenParser emptyDef)) 
    :: Num b => ParsecT String u Identity b 

을하지만 명시 적으로 타입 서명을 지정하지 않을 경우, 'B'유형은 어떻게 든 Word32에 고정되어있다 : 나는 GHCi에서 형식 정보를 조회 할 경우 동시에

은, 그것은 다음과 같습니다 .

을 두 개의 다른 (그러나 여전히 동일한 구현) 함수 parseUInt1parseUInt2으로 바꾸면 코드도 컴파일됩니다.

함수의 유형을 지정하지 않으면 추론 된 유형이 가장 제한 적이 지 않아야한다고 생각했지만 (어쨌든이 경우는 그렇지 않습니다.)

내가 실제로 여기에없는 이유는 무엇입니까?

+1

이것은 [Monomorphism restriction] (http://www.haskell.org/haskellwiki/Monomorphism_restriction)입니다. '{- # LANGUAGE NoMonomorphismRestriction # -}'을 추가하면 컴파일이 시작됩니다. @ GabrielGonzalez 및 @amalloy에게 감사드립니다. 난 당신의 대답을 upvote 수 있지만 아직 충분한 "명성"을 갖고 싶지 않아요. –

답변

8

나는 이것이 두려운 MonomorphismRestriction의 행동이라고 생각합니다. 형식 서명을 제공하지 않으면 ghc은 함수가 코드의 다른 곳에서 구체적인 형식으로 인스턴스화되면 구체 형식 서명을 유추합니다. ghcparsePairOfInt의 첫 번째 줄로 Word32을 구문 분석하는 함수를 사용하고 parseUInt' 두 줄 아래로 두 번째 사용하기 전에 해당 유형에 parseUInt'을 수정합니다. 형식이 이미 Word32으로 인스턴스화되었으므로 유형 오류가 발생합니다. 유형은 Word8이어야합니다.

+3

당신을 잊어 버렸습니다 * dreaded *. :) – augustss

+0

@augustss 고정! :) –

2

다시 monomorphism restriction처럼 보입니다. 당신은 다형성 값처럼 보이지 않는 것을 정의했기 때문에 컴파일러는 그것을위한 단일 형을 유추했다.

이것은 원하는 형식이 아니기 때문에 형식 서명을 추가하여 다형성을 사용한다는 것을 분명히해야합니다.