Re: [Haskell-cafe] [ghc-proposals/cafe] Partially applied type families

On Fri Jun 2 02:32:39 UTC 2017, Richard Eisenberg wrote:
On May 31, 2017, at 12:31 AM, Anthony Clayden wrote:
You could always view
instance TypeError ... => C Int Bool
as sugar for
instance C Int Bool fails
Yes I understand that. But no I don't want any instance. (Sugar on rotten fruit doesn't hide the smell.)
I hereby pronounce
instance TypeError ... => C Int Bool
as "not an instance". ...
Hmm. I'd be interested how you're going to stop the compiler matching some usage site to it.
In other words, I'm not sure what you're getting at here other than concrete syntax. How does not having an instance differ than the TypeError solution?
Good question. I've been struggling to explain it. Re-reading the Instance Chains paper has clarified the issue for me. And looking at Garrett's later 'Variations on Variants' paper. (Clarified, because that's a non-solution.) It's the Expression Problem: Once I have a catch-all instance (even if it has an impossible-to-fulfill constraint) the compiler is committed to selecting that instance. I can't introduce a new data type and new instance for it, because it'll overlap the catch-all instance. IIUC, Instance Chain's 'fail' is more powerful, it triggers back-tracking to look for another instance that doesn't fail. But we don't want to introduce backtracking into Haskell search for instances. Nevertheless, I can only write one Instance Chain per class. So I can't (say in another module) introduce a new datatype with instances. Sometimes closed/chained instances are the right solution. (That's the case for HList, for example. But even there I'm not convinced. I might want as well as HNil, HCons, a constructor with explicit type-labelling.) But sometimes closed instances are not right. I would say that where closed instances are needed, you can still achieve that with a 'catch-all' stand-alone instance, suitably guarded, of course. So I disagree with Garrett: not only do Instance Chains fail to solve the expression problem, they actually exacerbate it. (Same for Closed Type Families, or Closed Class Instances.)
OK. Perhaps you're seeing something I can't. To adapt your example from a parallel message, suppose: <snip>
What you're getting at here is that there may be interesting interplay between instance guards and OverlappingInstances. Indeed. This would have to be worked out (or left as an open question) in the proposal.
Regardless, I think that hashing out this level of detail here is the wrong place. ...
OK, fair enough.
Put it in the proposal! That way, the ensuing debate involves more of the community and persists better.
Oh! that I had "Deserts of vast eternity" to write the thing. As it is, it's easier to tackle as bite-size pieces on the forum. AntC

Hi Anthony, This conversation has become deeply mysterious to me. I understand that you're revisiting arguments on the structuring of conditionals that were tried and discarded in the 70s; what I don't understand is why you need to repeatedly mischaracterize my work to do so. For one example, I have no idea why you make the following claim:
Nevertheless, I can only write one Instance Chain per class. So I can't (say in another module) introduce a new datatype with instances.
The instance chains paper is quite explicit in ruling out this interpretation; when introducing the notion of chains, we wrote: In ilab, a class can be populated by multiple, non-overlapping instance chains, where each chain may contain multiple clauses (separated by the keyword else). For another, you give a fanciful description of the problems that might arise in implementing instance chains, including:
There's a persistent problem for the compiler testing for type equality: the usage sites must have the types grounded. It's often more successful to prove disequality.
and also:
I suspect that for the compiler, Instance Chains will be as problematic for type inference as with Closed Type Families: CTFs have a lot of searching under the covers to 'look ahead' for equations that can safely match.
Luckily, both instance chains and closed type families have formalizations that can be checked to evaluate these claims. In neither case do we find either equality limited to ground types or anything that should be construed as 'look ahead'. Perhaps you're trying to refer to the use of infinitary unification in checking apartness (but not in checking equality) for closed type families? Here again, not only is there no use of or need for infinitary unification with instance chains, but I discussed this difference and its consequences in my 2015 paper. Finally, you make various claims about what is and is not a solution to the expression problem which have no apparent relationship to any of the existing work on the expression problem or its encodings. The point of Swierstra's encoding is that you can give a complete definition of the interpretation of (right-recursive) coproducts, and that doing so is sufficient to encode extensible variants. The downside to his approach is that each new elimination of an extensible variant must itself be defined via a new type class. Subsequent work by Bahr, Oliveira et al., and myself, has lifted this restriction in various ways. At no point in any of these encodings is it in any sense necessary or desirable to extend existing instances for the coproduct, and so there is no reason to imagine that using either instance chains or closed type families would be any obstacle to implementing them. Again, this is all laid out, with examples, in my 2015 paper. /g

On Jun 2, 2017, at 3:22 AM, Anthony Clayden
wrote: I hereby pronounce
instance TypeError ... => C Int Bool
as "not an instance". ...
Hmm. I'd be interested how you're going to stop the compiler matching some usage site to it.
That's what TypeError does. When the compiler matches a use site, it issues an error. I would imagine that's the behavior you want.
In other words, I'm not sure what you're getting at here other than concrete syntax. How does not having an instance differ than the TypeError solution?
Good question. I've been struggling to explain it. ...
I'm afraid I didn't follow the description that followed. Can you write a concrete example of something you'd like to do that the current machinery doesn't?
Oh! that I had "Deserts of vast eternity" to write the thing. As it is, it's easier to tackle as bite-size pieces on the forum.
It's always OK to write a proposal with open questions, such as how the feature interacts with overlapping instances, what the concrete syntax should be, etc. But the enormous advantage to moving to a proposal is that we then have a concrete artifact to stare at and evaluate, instead of some hypothetical design which might be different in all our heads. Richard
participants (3)
-
Anthony Clayden
-
J. Garrett Morris
-
Richard Eisenberg