[Hugs-users] FunDeps: divergent improvement from overlapping instances
Anthony Clayden
anthony.d.clayden at gmail.com
Fri Aug 12 00:57:38 UTC 2022
> A precondition is that it scans instances in most-specific-first sequence
> -- which Hugs is already doing.
It galled me that going only by (an adapted notion of) overlap, I still had
to write three instances for a three-FunDep AddNat:
> class AddNat x y z | x y -> z, x z -> y, y z -> x
>
> instance AddNat Z Z Z
> instance AddNat Z (S y') (S y')
>
> instance AddNat x' y z' => AddNat (S x') y (S z')
>
because the 'obvious' way to write, with two instances (see below), put
them in no substitution ordering for the argument positions to the third
FunDep. So I dug out an idea from a few years ago (rejected proposal) and
implemented:
> instance AddNat Z y y
>
> instance AddNat x' y z' => AddNat (S x') y (S z') | y /~ (S z')
>
That after the `|` in the instance is an 'Instance Disequality Guard':
prefer a more specific instance if those two types from the head unify.
Then Hugs puts that instance later in the preference ordering than the
first instance -- because the instance heads unify going by the argument
positions, but the first instance has no guard.
This also works for the semi-overlap instances that Hugs currently
rejects/GHC accepts but might turn out to be unusable:
> class Semi a b
>
> instance Semi Int b
> instance Semi a Bool | a /~ Int
>
> [W] Semi Int Bool -- GHC currently rejects as ambiguous
The guard says: in case of [W] Semi Int Bool, prefer the Semi Int b
instance. We can even go:
> instance Semi Int Bool
>
> instance Semi Int b | b /~ Bool
> instance Semi a Bool | a /~ Int
>
> instance Semi a b -- no guard, because strictly more
general than any instance
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/hugs-users/attachments/20220812/cee4f324/attachment.html>
More information about the Hugs-Users
mailing list