코드 예제로 시작해 봅시다.
foob :: forall a b. (b -> b) -> b -> (a -> b) -> Maybe a -> b
foob postProcess onNothin onJust mval =
postProcess val
where
val :: b
val = maybe onNothin onJust mval
이 코드는 일반 Haskell 98에서 컴파일 (구문 오류)되지 않습니다 forall
. 키워드 를 지원하려면 확장이 필요합니다 .
기본적으로,이 셋 개이다 다른 일반적인에 사용하는 forall
키워드 (또는 적어도 그렇게 보인다는 ), 각 자체 하스켈 확장이 있습니다 ScopedTypeVariables
, RankNTypes
/ Rank2Types
, ExistentialQuantification
.
위의 코드는 활성화 된 구문 검사 중 오류가 발생하지 않고 활성화 된 유형 검사 만 수행합니다 ScopedTypeVariables
.
범위가 지정된 유형 변수 :
범위가 지정된 유형 변수는 코드 내부 where
절의 유형을 지정하는 데 도움이됩니다 . 그것은을 만들어 b
에 val :: b
는 AS 동일한 것을 b
에서 foob :: forall a b. (b -> b) -> b -> (a -> b) -> Maybe a -> b
.
혼란스러운 점 : forall
유형에서 생략 할 때 실제로 여전히 암시 적이라고 들릴 수 있습니다 . ( 노먼의 대답에서 : "일반적으로 이러한 언어는 다형성 유형에서 전체를 생략합니다" ). 이 주장은 정확 하지만 사용이 forall
아닌 다른 용도를 나타냅니다 ScopedTypeVariables
.
순위 -N- 타입 :
그것부터 시작하자 mayb :: b -> (a -> b) -> Maybe a -> b
에 해당합니다 mayb :: forall a b. b -> (a -> b) -> Maybe a -> b
, 를 제외시켰다 때를 위해 ScopedTypeVariables
사용할 수 있습니다.
이것은 모든 작동한다는 것을 의미 a
하고 b
.
이런 식으로하고 싶다고 가정 해 봅시다.
ghci> let putInList x = [x]
ghci> liftTup putInList (5, "Blah")
([5], ["Blah"])
이것의 유형은 무엇입니까 liftTup
? 이것의liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)
. 이유를 알아 보려면 코드를 작성해 보겠습니다.
ghci> let liftTup liftFunc (a, b) = (liftFunc a, liftFunc b)
ghci> liftTup (\x -> [x]) (5, "Hello")
No instance for (Num [Char])
...
ghci> -- huh?
ghci> :t liftTup
liftTup :: (t -> t1) -> (t, t) -> (t1, t1)
"흠. 왜 GHC는 튜플에 같은 유형의 두 개가 포함되어야한다고 추론 하는가?
-- test.hs
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)
ghci> :l test.hs
Couldnt match expected type 'x' against inferred type 'b'
...
흠. 그래서 여기 GHC은 우리가 적용 할 수 없습니다 liftFunc
에 v
있기 때문에 v :: b
와 liftFunc
을 원한다 x
. 우리는 함수가 가능한 모든 함수를 받아들이기를 원합니다.x
!
{-# LANGUAGE RankNTypes #-}
liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)
그래서 그렇지 않습니다 liftTup
모든 것이 작동 x
하지는 않습니다. 그것이 얻는 기능입니다.
기존 정량화 :
예를 들어 봅시다 :
-- test.hs
{-# LANGUAGE ExistentialQuantification #-}
data EQList = forall a. EQList [a]
eqListLen :: EQList -> Int
eqListLen (EQList x) = length x
ghci> :l test.hs
ghci> eqListLen $ EQList ["Hello", "World"]
2
Rank-N-Types와 다른 점은 무엇입니까?
ghci> :set -XRankNTypes
ghci> length (["Hello", "World"] :: forall a. [a])
Couldnt match expected type 'a' against inferred type '[Char]'
...
Rank-N-Types를 사용하면 forall a
식이 가능한 모든에 맞아야합니다 a
. 예를 들면 다음과 같습니다.
ghci> length ([] :: forall a. [a])
0
빈 목록은 모든 유형의 목록으로 작동합니다.
그래서 실존-정량화와 함께, forall
에이야 data
정의는 그 의미, 값이 포함되어 있습니다 될 어떤 그렇지 않은 것을, 적절한 형태 해야 될 모든 적절한 유형.