[GHC] #6018: Injective type families
GHC
ghc-devs at haskell.org
Tue Oct 14 10:05:18 UTC 2014
#6018: Injective type families
-------------------------------------+-------------------------------------
Reporter: lunaris | Owner: jstolarek
Type: feature | Status: new
request | Milestone: 7.10.1
Priority: normal | Version: 7.4.1
Component: Compiler | Keywords: TypeFamilies,
Resolution: | Injective
Operating System: | Architecture: Unknown/Multiple
Unknown/Multiple | Difficulty: Unknown
Type of failure: | Blocked By:
None/Unknown | Related Tickets: #4259
Test Case: |
Blocking: |
Differential Revisions: Phab:D202 |
-------------------------------------+-------------------------------------
Comment (by jstolarek):
Richard, either I'm not getting the subtleties of your arguments or you're
misunderstanding what I meant to say on the wiki page. Or both :-)
I now see the theoretical difference between "overlaps" and "subsumes" but
I don't yet see how that is important in my algorithm outline. I re-read
parts of the closed type families paper and now I'm not even sure whether
I meant "overlaps" or "unifies". Anyway, I believe that my thinking is
correct and in my algorithm I have addressed problems that you raised. It
looks that I need help with sorting out the terminology so things are
clear.
Now, looking at your examples:
{{{#!hs
type family E1 a = r | r -> a where
E1 Int = Int -- 1
E1 a = a -- 2
}}}
When my algorithm reaches (2) it will attempt to unify `a` with RHS of
equation (1). It will succeed with substitution `[ a -> Int ]`. It will
apply that substitution to the LHS of (2) and proceed with checking
whether after substitution this equation is subsumed (?) by any of the
earlier ones. Clearly, it is by the first equation and since this is the
last equation we declare `E1` to be injective. In other words I know that
(2) will never produce an `Int` since this will equation will never be
reached for `a` equal to `Int`.
Now `E2`:
{{{#!hs
type family E2 (a:: Bool) = r | r -> a where
E2 False = True
E2 True = False
E2 a = False
}}}
I consider almost identical example on the wiki:
{{{#!hs
type family Bak a = r | r -> a where
Bak Int = Char
Bak Char = Int
Bak a = a
}}}
The difference is the RHS of the last equation: a concrete type in your
example, a type variable in mine. Yet I believe that both examples are
intended to demonstrate the same problem - see discussion below that
example.
> In `IdNat` and `NatToMaybe`, unification fails before seeing the
recursive use of the type family.
Right. I assumed that noticing that allows us to conlcude that equations
of `IdNat` and `NatToMaybe` produce distinct types and thus these type
families are injective. Your reasoning in that whole paragraph completely
agrees with mine.
> But I'd want a proof first.
Agreed. As I said, I've been unable to produce a counter-example but that
doesn't meant that one does not exist.
I have a question about closed type families paper. Paragraph just after
Candidate Rule 2 (section 3.2, page 3) says: "As a notational convention,
apart(ρ, τ) considers the lists ρ and τ as tuples of types; the apartness
check does ''not'' go element-by-element.", where "not" is emphasized. Why
is this important? Seems like the choice of representing patterns and
types as tuples or lists is just an implementation detail.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/6018#comment:84>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list