#4226: Lifting constraints is questionably correct for implicit parameters.
-------------------------------+--------------------------------------------
Reporter: dolio | Owner:
Type: proposal | Status: new
Priority: normal | Component: Compiler (Type checker)
Version: 6.12.1 | Keywords: implicit parameters
Os: Linux | Testcase:
Architecture: x86_64 (amd64) | Failure: Other
-------------------------------+--------------------------------------------
Greetings,
While fooling with implicit parameters today, I encountered an anomaly.
Part of (I think) the justification of implicit parameters is that the
types inform you of what they do. So, for instance:
{{{
(\() -> ?x) :: (?x :: Int) => () -> Int
}}}
depends on an implicit parameter, while:
{{{
(let ?x = 5 in \() -> ?x) :: () -> Int
}}}
does not. However, I discovered that the following:
{{{
(let ?x = 5 in \() -> ?x) :: () -> ((?x :: Int) => Int)
}}}
generates a function whose implicit parameter {{{?x}}} is actually
unbound, so if we let that expression be {{{f}}}, then:
{{{
let ?x = 4 in f ()
}}}
yields 4. By contrast, if we give the type:
{{{
(let ?x = 5 in \() -> ?x) :: (?x :: Int) => () -> Int
}}}
the {{{?x}}} in the lambda expression ''is'' bound, and the implicit
parameter constraint is spurious (like {{{5 :: (?x :: Int) => Int}}}).
This happens for definitions in which types are given, so it does not seem
like it is a case of the note on monomorphism in the implicit parameters
documentation. For instance:
{{{
let f :: (?x :: Int) => () -> Int
f = let ?x = 5 in \() -> ?x
g :: () -> ((?x :: Int) => Int)
g = let ?x = 5 in \() -> ?x
in let ?x = 4
in (f (), g()) -- (5, 4)
}}}
This would arguably be fine, as the two have different types. However, GHC
does not actually distinguish them. Asking the type of either will
generate:
{{{(?x :: Int) => () -> Int}}}
Instead of the one with the higher-rank (so to speak) constraint.
I get this behavior using 6.12.1, but it seems unlikely that it would have
changed in the 6.12 series.
Strictly speaking, I'm not sure I can call this a bug. Due to context
weakening, there's probably no way to unambiguously clarify using types
which values are genuinely dependent on implicit parameters, and which are
not (similar to {{{ask}}} versus {{{local (const 5) ask}}} in
{{{Reader}}}). However, it seems odd that the type annotations make a
difference, yet are not subsequently distinguished. It's also conceivable
that the {{{() -> ((?x :: Int) => Int)}}} behavior is unintentional. I am
unsure which, if any, of these resolutions is appropriate.
So, instead, I'll call this a proposal, that we determine whether this is
the intended behavior (feel free to promote to a bug if it is decided that
something needs to be fixed, however). :)
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4226>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs