Type Inference in Patterns

老子叫甜甜 提交于 2019-12-05 06:47:00

The monomorphism restriction applies only to top level bindings. The compiler is aware of the real type of y, but there is no way to infer a monomorphic type for it; that is the cause of the type error. If you really would like to turn off monomorphic let bindings, you have to use the correct extension:

{-# LANGUAGE NoMonoLocalBinds #-}

With it, your code compiles.

For much more detail about monomorphic let bindings, see the ghc wiki.

I am not familiar with the typing algorithm of GHC. Still, here's my guess about why the compiler can not figure it out.

Consider this code:

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) =
  let y = ... :: Foo (Bar rp Char)
  in case (eqT :: Maybe (Char :~: rq)) of
     Just Refl -> y

This should compile, since matching Refl proves Char ~ rq, hence y at the end has the correct return type Foo (Bar rp rq). The program passes type checking.

However, suppose we instead have

  let y = ... :: Foo (Bar rp rq)

in this case, y has already the correct type, and the Refl is useless. Again, the program passes type checking.

Now, suppose we have no type annotation. How would the compile figure out which is the correct type for the let y = ... binding? After all, there are (at least) two of them leading to a correct typing of the whole rebar.

This may also explain why if you add _ -> y it does work: in that case the compiler knows that the Refl is not needed. Instead, if you add y -> error "" no information about y can be deduced.

The actual full story may be more complicated than the above: here I am conveniently ignoring the information coming from the definition of y, i.e. rebar p1 p2 x. In other words, I am only considering the constraints the context puts on the definition on y, and not those going in the other direction.

In your example the type equation is actually rp' ~ rp'' which seems irrelevant w.r.t. the type of y at the end. Maybe the compiler is not smart enough to figure that out.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!