Ryb*_*yba 7 haskell typeclass functional-dependencies gadt
在下面的代码中:
\nclass FD a b | a -> b\n\ndata Foo a where\n Foo :: FD a b => b -> Foo a\n\nunFoo :: FD a b => Foo a -> b\nunFoo (Foo x) = x\nRun Code Online (Sandbox Code Playgroud)\n根据常识,这应该可行,因为aGADT 和函数中的约束是相同的,并且它确定b,但是这不会编译并出现以下错误:
\xe2\x80\xa2 Couldn't match expected type \xe2\x80\x98b\xe2\x80\x99 with actual type \xe2\x80\x98b1\xe2\x80\x99\n \xe2\x80\x98b1\xe2\x80\x99 is a rigid type variable bound by\n a pattern with constructor:\n Foo :: forall a b. FD a b => b -> Foo a,\n in an equation for \xe2\x80\x98unFoo\xe2\x80\x99\n at src/Lib.hs:13:8-12\n \xe2\x80\x98b\xe2\x80\x99 is a rigid type variable bound by\n the type signature for:\n unFoo :: forall a b. FD a b => Foo a -> b\n at src/Lib.hs:12:1-29\n \xe2\x80\xa2 In the expression: x\n In an equation for \xe2\x80\x98unFoo\xe2\x80\x99: unFoo (Foo x) = x\n \xe2\x80\xa2 Relevant bindings include\n x :: b1 (bound at src/Lib.hs:13:12)\n unFoo :: Foo a -> b (bound at src/Lib.hs:13:1)\n |\n13 | unFoo (Foo x) = x\n | ^\nRun Code Online (Sandbox Code Playgroud)\n它不起作用有什么充分的理由吗?
\n@chi Fundeps 和 GADT 之间的相互作用……目前看起来相当糟糕。
我认为这比这更重要(不仅仅是“目前”,也不仅仅是 FunDeps)。
x无论编译器推断出in的类型
unFoo (Foo x) = ...
Run Code Online (Sandbox Code Playgroud)
仅在 RHS 上有效,在 的比赛中(Foo x)。尝试裸露返回x会让任何假设消失。
比较一个更古老的等价物:在我们有了 GADT 之前,就有存在量化的数据构造器,所以
data Foo' a = forall b. FD a b => Foo' b
unFoo' :: FD a b => Foo' a -> b
unFoo' (Foo' x) = x
Run Code Online (Sandbox Code Playgroud)
由于同样的原因无法编译。
或者尝试编写一个实例也会FD遇到同样的rigid type variable麻烦:
class FD a b | a -> b where
unFoom :: Foo a -> b
instance FD Int Bool where
unFoom (Foo x) = x -- Couldn't match expected type `Bool' with actual type `b'
Run Code Online (Sandbox Code Playgroud)
您可能会发现 Hugs 的错误消息更具启发性(对于存在数据类型)
*** Because : cannot instantiate Skolem constant
Run Code Online (Sandbox Code Playgroud)
我不相信这与 FunDeps 有很大关系。比较
data FooN a where
FooN :: Num b => b -> FooN a
unFooN :: Num b => FooN a -> b
-- unFooN (FooN x) = x + 1 -- rejected
unFooN (FooN x) = const undefined (x + 1) -- accepted (but useless)
z = 1 + unFooN (FooN 7) -- accepted (for useless unFooN)
Run Code Online (Sandbox Code Playgroud)
出于同样的原因被拒绝:该假设x :: Num b => b仅在比赛内有效。
补充:(回应评论)
扩展“仅在 RHS 上有效,在(Foo x)”上的比赛中:
(undefined :: Foo t)。)出于这些目的,FunDep 被视为任何其他约束,因此 OP 的问题就像这种FooN情况。(存在主义b仍然仅限于 RHS。)
@dfeuer使用类型族的重新设计不依赖于 tyvar 的范围b;类型族适用于a,其范围遍及整个unFoo. 这意味着F a具有相同的范围。由于神奇的~超类约束,unFoo的签名等效于:
unfoo: Foo a -> F a
Run Code Online (Sandbox Code Playgroud)
但这里是龙:F a不一定在任何地方都是格式良好的[第 3 节“总体陷阱”],因为代码不需要证据存在适用的实例。
所以我完全不同意 dfeuer 的观点:FunDep 确实携带证据,就像Num b示例一样,并且该证据无法逃脱模式匹配;类型族F a不携带证据(实例匹配的证据——~约束在没有证据的情况下成立),因此F a在整个范围内可用a——“可用”并不意味着有效。
| 归档时间: |
|
| 查看次数: |
193 次 |
| 最近记录: |