模式同义词与正常模式的绑定方式不同

时间:2017-11-30 02:04:16

标签: haskell singleton-type vinyl

函数f没有在下面的代码中键入check,它使用带有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)

对rhead的调用中的错误是Couldn't match type ‘rs1’ with ‘'[s2 :-> t1] - 基本上看起来好像模式匹配没有像我期望的那样绑定rs1的结构。但如果我内联模式,则输入检查:

f' :: forall rs1 rs2.  SList rs1 -> Frame (Record rs1) -> Int
f' (SCons (SRecArrow s1 t1) SNil) df1 = broadcast (*) (rhead <$> df1)

鉴于模式同义词应该是一个同义词,它不应该与内联模式完全相同吗?

1 个答案:

答案 0 :(得分:2)

模式同义词的定义是正确的;这是错误的类型。正确的类型是

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中,您没有这样的表达方式 - 对于某些x :: SList rs1,您只有rs1,这更为一般。使用正确的签名,您可以使用模式同义词来匹配此类表达式,因为模式同义词被声明为适用于任何SList rs;然后提供的约束(即rs ~ '[s :-> t])在模式匹配的范围内可用。

有关模式签名的其他详细信息,请参阅GHC user guide