[GHC] #6018: Injective type families

GHC ghc-devs at haskell.org
Tue Oct 14 12:30:42 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 goldfire):

 Replying to [comment:84 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".

 To be clear, I am considering the expressions "two types overlap" and "two
 types unify" to be synonymous. Subsumption is a finer, directed relation
 between types than overlap/unify.

 > {{{#!hs
 > type family E1 a = r | r -> a where ...
 > }}}

 Yes yes yes. You're right here. I was wrong. The wiki page is updated.

 >
 > 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.

 I think these cases are different. In yours, the RHS unification (`a`
 unifies with `Char`) refines the LHS (`a |-> Char`) so that it is subsumed
 by an earlier equation. This action does not happen in my example, and
 different reasoning (noting that `False` and `True` are both impossible)
 is required.

 > 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.

 Agreed that choosing a list vs. a tuple is irrelevant, but choosing
 element-by-element vs. as-a-whole is quite important. For example `(a, a)`
 is quite apart from `(Int, Bool)`, when considered as a whole, even though
 `a` is neither apart from `Int` nor `Bool` looking at individual elements.

 Does that clarify?

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/6018#comment:85>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list