【发布时间】:2014-11-10 11:17:21
【问题描述】:
我注意到 GHC 想要一个我认为应该推断的类型签名。我将我的示例最小化到此,这几乎肯定没有任何意义(我不建议在您最喜欢的类型上运行它):
{-# LANGUAGE GADTs, RankNTypes, ScopedTypeVariables,
TypeOperators, NoMonomorphismRestriction #-}
module Foo where
import Data.Typeable
data Bar rp rq
data Foo b = Foo (Foo b)
rebar :: forall rp rq rp' rp'' . (Typeable rp', Typeable rp'')
=> Proxy rp' -> Proxy rp'' -> Foo rp -> Foo (Bar rp rq)
rebar p1 p2 (Foo x) =
-- The signature for y should be inferred...
let y = rebar p1 p2 x -- :: Foo (Bar rp rq)
-- The case statement has nothing to do with the type of y
in case (eqT :: Maybe (rp' :~: rp'')) of
Just Refl -> y
y 的定义上没有类型签名,我得到错误:
Foo.hs:19:20:
Couldn't match type ‘rq0’ with ‘rq’
‘rq0’ is untouchable
inside the constraints (rp' ~ rp'')
bound by a pattern with constructor
Refl :: forall (k :: BOX) (a1 :: k). a1 :~: a1,
in a case alternative
at testsuite/Foo.hs:19:12-15
‘rq’ is a rigid type variable bound by
the type signature for
rebar :: (Typeable rp', Typeable rp'') =>
Proxy rp' -> Proxy rp'' -> Foo rp -> Foo (Bar rp rq)
at testsuite/Foo.hs:12:20
Expected type: Foo (Bar rp rq)
Actual type: Foo (Bar rp rq0)
Relevant bindings include
y :: Foo (Bar rp rq0) (bound at testsuite/Foo.hs:16:7)
rebar :: Proxy rp' -> Proxy rp'' -> Foo rp -> Foo (Bar rp rq)
(bound at testsuite/Foo.hs:14:1)
In the expression: y
In a case alternative: Just Refl -> y
Failed, modules loaded: none.
由于在多种情况下受到可怕的单态限制,我打开了NoMonomorphismRestriction,但这并没有改变行为。
为什么y的类型没有被推断为函数的输出类型?
【问题讨论】:
-
我一点也不知道。不过我发现了一个有趣的事实:如果你在“Just Refl -> y”下添加“_ -> y”,它会起作用。
-
@AndrásKovács 很奇怪!但是
_ -> error ""不起作用! -
@leftaroundabout 在this answer 中提到,“尽管如此,即使没有 RankNTypes 代码中的单态限制,同样的 [推理问题] 也会出现,但无法完全避免。”关于我的代码究竟是什么可能导致它落入这个“有问题的 RankNTypes”类别的任何想法?