模式同义词绑定不同于普通模式
Pattern synonym binds differently from normal pattern
函数 f 在以下代码中没有类型检查,它使用带有 Frames 和 Vinyl 的单例:
f :: forall rs1 rs2. SList rs1 -> Frame (Record rs1) -> Int
f (OnlyRecord s1 t1) df1 = broadcast (*) (rhead <$> df1)
pattern OnlyRecord :: Sing s -> Sing t -> SList '[s :-> t]
pattern OnlyRecord sym typsing = SCons (SRecArrow sym typsing) SNil
rhead :: Record ((s :-> t) ': sstt) -> t
rhead (x :& xs) = getCol $ getIdentity x
data instance Sing (a :: Type) where
SRecArrow :: Sing (s :: Symbol) -> Sing (t :: Type) -> Sing (s :-> t)
错误是 Couldn't match type ‘rs1’ with ‘'[s2 :-> t1]
在对 rhead 的调用中——基本上模式匹配似乎没有像我期望的那样绑定 rs1 的结构。但是如果我内联模式,它会输入检查:
f' :: forall rs1 rs2. SList rs1 -> Frame (Record rs1) -> Int
f' (SCons (SRecArrow s1 t1) SNil) df1 = broadcast (*) (rhead <$> df1)
鉴于模式同义词应该是同义词,它不应该与内联模式一样工作吗?
模式同义词定义正确;这是错误的类型。正确的类型是
pattern OnlyRecord :: () => (rs ~ '[s :-> t]) => Sing s -> Sing t -> SList rs
pattern OnlyRecord ...
使用您的原始模式类型签名(相当于 () => () => Sing s -> Sing t -> SList '[s :-> t]
),您声称给定一个表达式 x :: SList '[s :-> t]
您可以使用您的模式同义词匹配该表达式。但是,在 f
中,您没有这样的表达式 - 对于某些 rs1
,您只有 x :: SList rs1
,这更笼统。使用正确的签名,您可以使用模式同义词来匹配这样的表达式,因为模式同义词被声明为适用于任何SList rs
;然后提供的约束(即rs ~ '[s :-> t]
)在模式匹配范围内可用。
有关模式签名的更多详细信息,请参阅 GHC user guide。
函数 f 在以下代码中没有类型检查,它使用带有 Frames 和 Vinyl 的单例:
f :: forall rs1 rs2. SList rs1 -> Frame (Record rs1) -> Int
f (OnlyRecord s1 t1) df1 = broadcast (*) (rhead <$> df1)
pattern OnlyRecord :: Sing s -> Sing t -> SList '[s :-> t]
pattern OnlyRecord sym typsing = SCons (SRecArrow sym typsing) SNil
rhead :: Record ((s :-> t) ': sstt) -> t
rhead (x :& xs) = getCol $ getIdentity x
data instance Sing (a :: Type) where
SRecArrow :: Sing (s :: Symbol) -> Sing (t :: Type) -> Sing (s :-> t)
错误是 Couldn't match type ‘rs1’ with ‘'[s2 :-> t1]
在对 rhead 的调用中——基本上模式匹配似乎没有像我期望的那样绑定 rs1 的结构。但是如果我内联模式,它会输入检查:
f' :: forall rs1 rs2. SList rs1 -> Frame (Record rs1) -> Int
f' (SCons (SRecArrow s1 t1) SNil) df1 = broadcast (*) (rhead <$> df1)
鉴于模式同义词应该是同义词,它不应该与内联模式一样工作吗?
模式同义词定义正确;这是错误的类型。正确的类型是
pattern OnlyRecord :: () => (rs ~ '[s :-> t]) => Sing s -> Sing t -> SList rs
pattern OnlyRecord ...
使用您的原始模式类型签名(相当于 () => () => Sing s -> Sing t -> SList '[s :-> t]
),您声称给定一个表达式 x :: SList '[s :-> t]
您可以使用您的模式同义词匹配该表达式。但是,在 f
中,您没有这样的表达式 - 对于某些 rs1
,您只有 x :: SList rs1
,这更笼统。使用正确的签名,您可以使用模式同义词来匹配这样的表达式,因为模式同义词被声明为适用于任何SList rs
;然后提供的约束(即rs ~ '[s :-> t]
)在模式匹配范围内可用。
有关模式签名的更多详细信息,请参阅 GHC user guide。