tcfail143.hs 3.42 KB
Newer Older
1 2
{-# LANGUAGE UndecidableInstances, FlexibleInstances,
             MultiParamTypeClasses, FunctionalDependencies #-}
3

thomie's avatar
thomie committed
4
module Foo  where
5

thomie's avatar
thomie committed
6 7
data Z          = Z
data S a        = S a
8 9

class MinMax a b c d | a b -> c d, a c d -> b, b c d -> a
10 11 12
instance MinMax Z Z Z Z -- (a)
instance MinMax a Z Z a -- (b)   -- L1: wrongly flagged as error src.
instance MinMax Z b Z b -- (c)
13
instance MinMax a b c d => MinMax (S a) (S b) (S c) (S d)
14
                        -- (d)
15 16 17

class Extend a b  where extend :: a -> b ->  b
instance Extend Z b where  Z `extend` b = b
thomie's avatar
thomie committed
18 19
instance MinMax a b _c b  => Extend a b where
        _a `extend` b = b
20

thomie's avatar
thomie committed
21 22
t       :: MinMax a b _c d => a -> b -> d
t _ _   = (undefined :: d)
23

thomie's avatar
thomie committed
24 25
n0      = Z
n1      = S n0
26

thomie's avatar
thomie committed
27
t1 = n1 `t` n0      -- L2
28 29

t2 = n1 `extend` n0 -- L3: uncommenting just this line produces
thomie's avatar
thomie committed
30 31
                    --     an error message pointing at L1 and L2
                    --     with no mention of the real culprit, L3.
32

thomie's avatar
thomie committed
33 34
-- t1   :: S Z      -- L4: uncommenting this and L3 produces an
                    --  error message rightly pointing at L2 and L3.
35 36


37 38 39 40 41 42 43 44 45 46
{-  n0 :: Z;  n1 :: S Z

Call of extend gives wanted: Extend (S Z) Z
Use instance =>  MinMax (S Z) Z gamma Z
FD on (b) => gamma ~ Z, Z ~ S Z
             =>  MinMax (S Z) Z Z Z
FD on (a), 3rd fundep => Z ~ S Z
      (b) again (sadly)   Z ~ S Z

-}
47 48 49 50 51 52 53 54
{-

Here's what is happening.

Lacking the type signature t1 :: S Z, we get

  n0 :: Z
  n1 :: S v1
thomie's avatar
thomie committed
55 56
  t1 :: d1      with constraint ([L2] MinMax (S v1) Z c1 d1)
  t2 :: Z       with constraint ([L3] Extend (S v1) Z)
57 58

     [L2] MinMax (S v1) Z c1 d1, [L3] Extend (S v1) Z
thomie's avatar
thomie committed
59
--->    <by instance for Extend a b>
60
     [L2] MinMax (S v1) Z c1 d1, [L3] MinMax (S v1) Z c2 Z}
thomie's avatar
thomie committed
61
--->    <combining these two constraints using (a b -> c d)
62 63 64 65 66
     [L2] MinMax (S v1) Z c1 Z, [L3] MinMax (S v1) Z c1 Z}

Now there are the two constraints are indistinguishable,
and both give rise to the same error:

thomie's avatar
thomie committed
67 68
--->    <combining first with [L1] instance MinMax a Z Z a>
     c1=Z, Z=S v1       ERROR
69 70 71 72 73 74 75

In either case, the error points to L1.


A different sequence leads to a different error:

     [L2] MinMax (S v1) Z c1 d1, [L3] Extend (S v1) Z
thomie's avatar
thomie committed
76
--->    <by instance for Extend a b>
77
     [L2] MinMax (S v1) Z c1 d1, [L3] MinMax (S v1) Z c2 Z}
thomie's avatar
thomie committed
78
--->    <combining first with [L1] instance MinMax a Z Z a>
79 80 81 82 83 84 85 86 87
     [L2] MinMax (S v1) Z Z (S2 v1), [L3] MinMax (S v1) Z c2 Z}

Now combining the two constraints gives rise to the error, but
this time pointing to L2,L3.

I can't explain exactly why adding the type signature for t1
changes the order.


thomie's avatar
thomie committed
88
Hmm.  Perhaps a good improvement strategy would be:
89
  - first do improvement against the instance declarations
90 91
  - and only then do pairwise improvement between constraints

thomie's avatar
thomie committed
92
I've implemented that, and indeed it improves the result.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
Instead of:

  Foo.hs:1:0:
    Couldn't match `S Z' against `Z'
      Expected type: S Z
      Inferred type: Z
    When using functional dependencies to combine
      MinMax a Z Z a, arising from the instance declaration at Foo.hs:10:0
      MinMax (S Z) Z _c d, arising from use of `t' at Foo.hs:25:8-10

we get

  Foo.hs:1:0:
    Couldn't match `S Z' against `Z'
      Expected type: S Z
      Inferred type: Z
    When using functional dependencies to combine
      MinMax a Z Z a, arising from the instance declaration at Foo.hs:10:0
      MinMax (S Z) Z _c Z, arising from use of `extend' at Foo.hs:27:8-15


And this error in t2 is perfectly correct.  You get it even if you comment
out the entire definition of t1.
thomie's avatar
thomie committed
116
-}