2012-05-03 2 views
7

(용서하십시오 끔찍하게 인위적인 예)"where"절에서 표현식 제네릭 형식을 어떻게 제공합니까?

는 내가하고 싶은 것은 어디 절에서 유형을 지정할 수 있습니다 :

somemap :: (a -> b) -> [a] -> [b] 
somemap f xs = ys 
    where 
    some = take 5 xs :: [a] 
    ys = map f some :: [b] 

을하지만이 오류가 발생합니다

*Main> :load file.hs 
[1 of 1] Compiling Main    (file.hs, interpreted) 

fil.hs:15:18: 
    Couldn't match expected type `a1' against inferred type `a' 
     `a1' is a rigid type variable bound by 
      an expression type signature at file.hs:15:25 
     `a' is a rigid type variable bound by 
      the type signature for `somemap' at file.hs:12:12 
     Expected type: [a1] 
     Inferred type: [a] 
    In the second argument of `take', namely `xs' 
    In the expression: take 5 xs :: [a] 

file.hs:16:13: 
    Couldn't match expected type `b1' against inferred type `b' 
     `b1' is a rigid type variable bound by 
      an expression type signature at file.hs:16:24 
     `b' is a rigid type variable bound by 
      the type signature for `somemap' at file.hs:12:17 
    In the first argument of `map', namely `f' 
    In the expression: map f some :: [b] 
    In the definition of `ys': ys = map f some :: [b] 
Failed, modules loaded: none. 

구체적인 유형을 지정하는 경우 a 및을 Int으로 대체하십시오. b에 대한 335,453,210은 아무 문제 : 그래서 제 질문은

somemap :: (Int -> Bool) -> [Int] -> [Bool] 
somemap f xs = ys 
    where 
    some = take 5 xs :: [Int] 
    ys = map f some :: [Bool] 

없습니다

: 어떻게 일반적인 유형을 지정하고 어디 절에 제약을 입력합니까? where 절 내부

답변

15

, 형태 변수 ab새로운 타입의 변수는; 형식 변수는 범위가 지정되지 않으므로 최상위 수준에서 정의 된 것처럼 모든 형식 서명에 새 형식이 제공됩니다.

당신이 ScopedTypeVariables 확장을 설정하면 (파일의 맨 위에 {-# LANGUAGE ScopedTypeVariables #-}을 넣어), 그리고에 somemap의 유형 선언을 변경

somemap :: forall a b. (a -> b) -> [a] -> [b] 

다음 지정한 where 절 정의가 제대로 작동합니다. 나는 forall이 이전 버전과의 호환성에서만 필요하므로 다형성 값에 대해 where 절에 유형 변수를 재사용하는 코드가 손상되지 않는다고 생각합니다.

확장명을 사용하지 않으려면 asTypeOf과 같은 형식을 통합하는 추악한 도우미 함수를 정의해야합니다.

+1

http://stackoverflow.com/questions/7408911/haskell-magical-code-whats-going-on-here의 코드는 그러한 "추악한 도우미 기능"에서 발생할 수있는 혼란의 좋은 예입니다. –

관련 문제