我尝试理解使用forall
来量化两个类型变量和使用forall
来量化元组类型中单个类型变量之间的区别。
例如,给定以下类型族:
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
type family Fst (p :: (a,b)) :: a where
Fst '(a,_) = a
type family Snd (p :: (a,b)) :: b where
Snd '(_,b) = b
type family Pair (p :: (Type,Type)) :: Type where
Pair '(a,b) = (a,b)
我可以使用两个类型变量定义一对标识,并在GHC 8.0.1上编译它:
ex0 :: forall (a :: Type) (b :: Type). Pair '(a,b) -> (Fst '(a,b), Snd '(a,b))
ex0 = id
然而,如果我使用一个元组类型变量,则相同的定义无法编译:
ex1 :: forall (p :: (Type,Type)). Pair p -> (Fst p, Snd p)
ex1 = id
-- Ex.hs:20:7: error:
-- • Couldn't match type ‘Pair p’ with ‘(Fst p, Snd p)’
-- Expected type: Pair p -> (Fst p, Snd p)
-- Actual type: (Fst p, Snd p) -> (Fst p, Snd p)
-- • In the expression: id
-- In an equation for ‘ex1’: ex1 = id
-- • Relevant bindings include
-- ex1 :: Pair p -> (Fst p, Snd p) (bound at Ex.hs:20:1)
问题是 p
可能是 ⊥
吗?
Any
将无法与(Fst Any, Snd Any)
区分开来,从而验证 eta 规则。 - András KovácsAny
仍然是相关的,因为它对于余积来说是一个问题——或者例如如果(,)
在Agda中被定义为data
类型而不是record
。 - luquiAny
使余积 eta 失效,但类型检查器几乎从不检查余积 eta。(但我也认为摆脱Any
是好的)。 - András Kovács