【发布时间】:2021-11-08 14:41:35
【问题描述】:
我观察到一些我不太理解的行为。这是一个 MWE
{-# Language PatternSynonyms, GADTs #-}
module Test where
data Succ a
data Zero
data Vec n a where
EmptyVec :: Vec Zero a
(:+) :: a -> Vec n a -> Vec (Succ n) a
newtype Comp f g a = Comp (f (g a))
pattern CEv :: () => (n ~ Zero) => Comp (Vec n) g a
pattern CEv = Comp EmptyVec
t :: Comp (Vec m) (Vec n) r -> Bool
t (Comp (_ :+ _)) = True
t CEv = False
这编译。但是我们可能会注意到CEv 有两个约束,() => 和(n ~ Zero) =>。由于其中一个是空的,因此删除它不会有任何危害吗?好吧,如果我们删除它 t 就会中断。
pattern CEv :: (n ~ Zero) => Comp (Vec n) g a
pattern CEv = Comp EmptyVec
/XXXXXXX/src/Test.hs:18:3: error:
• Couldn't match type ‘m’ with ‘Zero’ arising from a pattern
‘m’ is a rigid type variable bound by
the type signature for:
t :: forall m n r. Comp (Vec m) (Vec n) r -> Bool
at src/Test.hs:16:1-35
• In the pattern: CEv
In an equation for ‘t’: t CEv = False
• Relevant bindings include
t :: Comp (Vec m) (Vec n) r -> Bool (bound at src/Test.hs:17:1)
|
18 | t CEv = False
| ^^^
我真的不知道这里发生了什么。为什么删除一个空约束会导致它中断?这两种类型有什么区别?
【问题讨论】:
-
在常规定义中
foo :: c => d => T等价于foo :: (c,d) => T,如果c为空,则可以在两种形式中将其删除。但是,在模式同义词中,符号pattern Foo :: c => d => T具有不同的含义,如下面的 Li-yao Xia 的回答中所解释的那样。也许以不同的含义重用相同的语法并不是那么明智(耸耸肩)。