2014-06-24 7 views
4

(제 용어가 잘못되어 사과드립니다.) 인라인 유형에 사용되는 유형 변수를 지정하는 방법은 함수 정의에 사용되는 유형 변수와 동일합니까?

나는 예외를 처리하는 래퍼 함수 작성하려고 해요 : 주어진 IO 조치가 발생하면, 그것은 (물론의 IO 컨텍스트 내에서) Nothing을 반환을하지만, 주어진 IO 작업이 성공하면, 그것은 Just v를 반환합니다.

tryMaybe :: IO a -> IO (Maybe a) 
tryMaybe action = do 
    result <- (try action) :: IO (Either SomeException a) 
    return $ case result of 
     Left _ -> Nothing 
     Right v -> Just v 

이 컴파일러 오류 메시지가 발생합니다

Couldn't match type `a' with `a1' 
     `a' is a rigid type variable bound by 
      the type signature for tryMaybe :: IO a -> IO (Maybe a) 
      at src/Database.hs:33:13 
     `a1' is a rigid type variable bound by 
      an expression type signature: IO (Either SomeException a1) 
      at src/Database.hs:35:15 
    Expected type: IO a1 
     Actual type: IO a 
    In the first argument of `try', namely `action' 

내가 첫 번째 줄에서 입력 변수 a는 세 번째 줄에있는 a와 동일하지 않습니다 같은데요 - 그들은 단지 소스 코드에서 같은 이름을 가지면 오류 메시지에서 컴파일러가 a1의 이름을 바꿉니다.

그럼 하스켈에게 이들이 같은 유형이라고 어떻게 말합니까?

+4

'ScopedTypeVariables'을 사용해 보셨나요? – bheklilr

+1

관련 설명 : http://stackoverflow.com/questions/15800878/scoped-type-variables-require-explicit-foralls-why – stusmith

답변

10

당신은 ScopedTypeVariables 확장을 활성화해야하고, 변화는 최상위 함수의 유형 서명은 forall a .로 시작 :

{-# LANGUAGE ScopedTypeVariables #-} 

... 

tryMaybe :: forall a . IO a -> IO (Maybe a) 
... 

forall 구문은 몸 전체에 대한 범위로 유형 변수 a을 제공합니다 tryMaybe인데, 이는 기본값 인 유형 서명으로 제한되지 않습니다. 이것은 주로 고의적 인 디자인보다는 역사적인 예외입니다.

+6

아하 그래, 그걸 분류 했어. GHC가 Haskell 98과의 호환성을 유지하려고 노력하고 있다는 것을 이해합니다.하지만 타입 가변 섀도 잉에 대한 경고 (올바른 용어 인 경우)와 그 언어 확장을 조사하는 힌트가 나 같은 초보자에게 도움이 될 것입니다. . 아 ~ 나는 살고 배웁니다. 많은 감사합니다! – stusmith

+5

@stusmith 나는 그림자 경고가 좋은 생각이라고 생각한다. ghc 개선 티켓을 제출해야합니다. – augustss

+1

GHC 티켓 제기 : https://ghc.haskell.org/trac/ghc/ticket/9244 – stusmith