Fundeps work even for unary type classes
authorSimon Peyton Jones <simonpj@microsoft.com>
Wed, 26 Oct 2016 09:54:16 +0000 (10:54 +0100)
committerSimon Peyton Jones <simonpj@microsoft.com>
Wed, 26 Oct 2016 10:13:18 +0000 (11:13 +0100)
The functional-dependency improvement functions,
   improveFromAnother
   improveFromInstEnv
had a side-condition that said the type class has to have at
least two arguments.  But not so, as Trac #12763 shows:

   class C a | -> a where ...

is perfectly legal, albeit a bit of a corner case.

compiler/typecheck/FunDeps.hs
testsuite/tests/typecheck/should_compile/T12763.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/T12763.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/all.T
testsuite/tests/typecheck/should_fail/T5684.stderr

index c40be7b..a42f7b4 100644 (file)
@@ -166,7 +166,7 @@ improveFromAnother :: loc
 improveFromAnother loc pred1 pred2
   | Just (cls1, tys1) <- getClassPredTys_maybe pred1
   , Just (cls2, tys2) <- getClassPredTys_maybe pred2
-  , tys1 `lengthAtLeast` 2 && cls1 == cls2
+  , cls1 == cls2
   = [ FDEqn { fd_qtvs = [], fd_eqs = eqs, fd_pred1 = pred1, fd_pred2 = pred2, fd_loc = loc }
     | let (cls_tvs, cls_fds) = classTvsFds cls1
     , fd <- cls_fds
@@ -199,7 +199,6 @@ improveFromInstEnv _inst_env _ pred
   = panic "improveFromInstEnv: not a class predicate"
 improveFromInstEnv inst_env mk_loc pred
   | Just (cls, tys) <- getClassPredTys_maybe pred
-  , tys `lengthAtLeast` 2
   , let (cls_tvs, cls_fds) = classTvsFds cls
         instances          = classInstances inst_env cls
         rough_tcs          = roughMatchTcs tys
diff --git a/testsuite/tests/typecheck/should_compile/T12763.hs b/testsuite/tests/typecheck/should_compile/T12763.hs
new file mode 100644 (file)
index 0000000..6c66ee1
--- /dev/null
@@ -0,0 +1,13 @@
+{-# LANGUAGE FunctionalDependencies #-}
+{-# OPTIONS_GHC -ddump-types #-}
+
+module T12763 where
+
+class C a | -> a where
+   m :: a -> ()
+
+instance C Int where
+  m = undefined
+
+-- Expecting inferred type f :: Int -> ()
+f x = m x
diff --git a/testsuite/tests/typecheck/should_compile/T12763.stderr b/testsuite/tests/typecheck/should_compile/T12763.stderr
new file mode 100644 (file)
index 0000000..0b38463
--- /dev/null
@@ -0,0 +1,14 @@
+TYPE SIGNATURES
+  f :: Int -> ()
+  m :: forall a. C a => a -> ()
+TYPE CONSTRUCTORS
+  class C a | -> a where
+    m :: a -> ()
+    {-# MINIMAL m #-}
+COERCION AXIOMS
+  axiom T12763.N:C :: C a = a -> () -- Defined at T12763.hs:6:1
+INSTANCES
+  instance C Int -- Defined at T12763.hs:9:10
+Dependent modules: []
+Dependent packages: [base-4.9.0.0, ghc-prim-0.5.0.0,
+                     integer-gmp-1.0.0.1]
index 67debd4..93f1b5f 100644 (file)
@@ -550,3 +550,4 @@ test('T12427b', normal, compile, [''])
 test('T12507', normal, compile, [''])
 test('T12734', normal, compile, [''])
 test('T12734a', normal, compile_fail, [''])
+test('T12763', normal, compile, [''])
index 673b7de..ed2af70 100644 (file)
@@ -8,21 +8,13 @@ T5684.hs:20:12: error:
           flop1 = [op False False, op 'c' undefined, op True undefined]
 
 T5684.hs:24:12: error:
-    • No instance for (B Char b10) arising from a use of ‘op’
+    • No instance for (B Char b5) arising from a use of ‘op’
     • In the expression: op 'c' undefined
       In the expression:
         [op False False, op 'c' undefined, op True undefined]
       In an equation for ‘flop1’:
           flop1 = [op False False, op 'c' undefined, op True undefined]
 
-T5684.hs:25:12: error:
-    • No instance for (A b11) arising from a use of ‘op’
-    • In the expression: op True undefined
-      In the expression:
-        [op False False, op 'c' undefined, op True undefined]
-      In an equation for ‘flop1’:
-          flop1 = [op False False, op 'c' undefined, op True undefined]
-
 T5684.hs:29:12: error:
     • No instance for (A Bool) arising from a use of ‘op’
     • In the expression: op False False
@@ -31,16 +23,8 @@ T5684.hs:29:12: error:
       In an equation for ‘flop2’:
           flop2 = [op False False, op True undefined, op 'c' undefined]
 
-T5684.hs:30:12: error:
-    • No instance for (A b8) arising from a use of ‘op’
-    • In the expression: op True undefined
-      In the expression:
-        [op False False, op True undefined, op 'c' undefined]
-      In an equation for ‘flop2’:
-          flop2 = [op False False, op True undefined, op 'c' undefined]
-
 T5684.hs:31:12: error:
-    • No instance for (B Char b9) arising from a use of ‘op’
+    • No instance for (B Char b4) arising from a use of ‘op’
     • In the expression: op 'c' undefined
       In the expression:
         [op False False, op True undefined, op 'c' undefined]
@@ -48,21 +32,13 @@ T5684.hs:31:12: error:
           flop2 = [op False False, op True undefined, op 'c' undefined]
 
 T5684.hs:35:12: error:
-    • No instance for (B Char b6) arising from a use of ‘op’
+    • No instance for (B Char b3) arising from a use of ‘op’
     • In the expression: op 'c' undefined
       In the expression:
         [op 'c' undefined, op True undefined, op False False]
       In an equation for ‘flop3’:
           flop3 = [op 'c' undefined, op True undefined, op False False]
 
-T5684.hs:36:12: error:
-    • No instance for (A b7) arising from a use of ‘op’
-    • In the expression: op True undefined
-      In the expression:
-        [op 'c' undefined, op True undefined, op False False]
-      In an equation for ‘flop3’:
-          flop3 = [op 'c' undefined, op True undefined, op False False]
-
 T5684.hs:37:12: error:
     • No instance for (A Bool) arising from a use of ‘op’
     • In the expression: op False False
@@ -72,7 +48,7 @@ T5684.hs:37:12: error:
           flop3 = [op 'c' undefined, op True undefined, op False False]
 
 T5684.hs:40:12: error:
-    • No instance for (B Char b4) arising from a use of ‘op’
+    • No instance for (B Char b2) arising from a use of ‘op’
     • In the expression: op 'c' undefined
       In the expression:
         [op 'c' undefined, op False False, op True undefined]
@@ -87,24 +63,8 @@ T5684.hs:41:12: error:
       In an equation for ‘flop4’:
           flop4 = [op 'c' undefined, op False False, op True undefined]
 
-T5684.hs:42:12: error:
-    • No instance for (A b5) arising from a use of ‘op’
-    • In the expression: op True undefined
-      In the expression:
-        [op 'c' undefined, op False False, op True undefined]
-      In an equation for ‘flop4’:
-          flop4 = [op 'c' undefined, op False False, op True undefined]
-
-T5684.hs:46:12: error:
-    • No instance for (A b3) arising from a use of ‘op’
-    • In the expression: op True undefined
-      In the expression:
-        [op True undefined, op 'c' undefined, op False False]
-      In an equation for ‘flop5’:
-          flop5 = [op True undefined, op 'c' undefined, op False False]
-
 T5684.hs:47:12: error:
-    • No instance for (B Char b2) arising from a use of ‘op’
+    • No instance for (B Char b1) arising from a use of ‘op’
     • In the expression: op 'c' undefined
       In the expression:
         [op True undefined, op 'c' undefined, op False False]
@@ -119,14 +79,6 @@ T5684.hs:48:12: error:
       In an equation for ‘flop5’:
           flop5 = [op True undefined, op 'c' undefined, op False False]
 
-T5684.hs:52:12: error:
-    • No instance for (A b0) arising from a use of ‘op’
-    • In the expression: op True undefined
-      In the expression:
-        [op True undefined, op False False, op 'c' undefined]
-      In an equation for ‘flop6’:
-          flop6 = [op True undefined, op False False, op 'c' undefined]
-
 T5684.hs:53:12: error:
     • No instance for (A Bool) arising from a use of ‘op’
     • In the expression: op False False
@@ -136,7 +88,7 @@ T5684.hs:53:12: error:
           flop6 = [op True undefined, op False False, op 'c' undefined]
 
 T5684.hs:54:12: error:
-    • No instance for (B Char b1) arising from a use of ‘op’
+    • No instance for (B Char b0) arising from a use of ‘op’
     • In the expression: op 'c' undefined
       In the expression:
         [op True undefined, op False False, op 'c' undefined]