use*_*543 3 haskell typechecking rank-n-types
我试图了解RankNTypes。
为什么编译器在这种情况下可以抱怨a不能是[a]?
> :{
> | tupleF2 :: (forall a . a -> b) -> (a1, a2) -> (b, b)
> | tupleF2 elemF2 (x, y) = (elemF2 x, elemF2 y)
> | :}
> :t tupleF2 tupleF2 :: (forall a. a -> b) -> (a1, a2) -> (b, b)
> :t tupleF2 length
<interactive>:1:9: error:
• Couldn't match type ‘a’ with ‘[a0]’
‘a’ is a rigid type variable bound by
a type expected by the context:
forall a. a -> Int
at <interactive>:1:1-14
Expected type: a -> Int
Actual type: [a0] -> Int
• In the first argument of ‘tupleF2’, namely ‘length’
In the expression: tupleF2 length
Run Code Online (Sandbox Code Playgroud)
虽然以下类型检查正常吗?并且t可以t a。
> :t tupleF length
tupleF length :: Foldable t => (t a, t a) -> (Int, Int)
:t tupleF
tupleF :: (t -> b) -> (t, t) -> (b, b)
Run Code Online (Sandbox Code Playgroud)
上面的编译失败仅发生在启用时RankNTypes。任何了解正在发生的事情的指针都会很棒。
谢谢。
forall a . a -> b是函数的类型f,可以将任何类型的值转换为type a的某些值b。注意,f必须准备好接受绝对任何东西作为输入,即所有这些都必须键入check
f ()
f 32
f True
f 'a'
f "hello"
f (True, [2], False)
Run Code Online (Sandbox Code Playgroud)
length不满足要求,因为例如length ()输入错误- length想要一个可折叠的(例如列表)作为输入,()因此不可以。
因此,tupleF2 length是病态的打字。
务实地,请注意f只能是一个常数函数,例如
f x = True -- assuming b = Bool
Run Code Online (Sandbox Code Playgroud)
确实,参数性保证只有常数函数才能具有type forall a . a -> b。您可以尝试tupleF2 (const True) ((),"hello")获取(True, True)。