yet another very simple overlapping instance example
Hi! Can somebody explain to me why ghc/hugs fails to compile the following Haskell program? As long as MyInt is not an instance of Num the compilations should succed... but it don't. :-( Why? $ cat multi.hs data MyInt = MyInt Int deriving Show class Op_plus a b where plus :: a -> b -> Int instance Op_plus MyInt MyInt where (MyInt a) `plus` (MyInt b) = a + b instance (Num a) => Op_plus a MyInt where i `plus` (MyInt b) = i + b instance (Num a) => Op_plus MyInt a where (MyInt b) `plus` i = i + b $ ghci \ -fglasgow-exts \ -fallow-overlapping-instances \ -fallow-undecidable-instances multi.hs ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 5.04.2, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base ... linking ... done. Loading package haskell98 ... linking ... done. Compiling Main ( multi.hs, interpreted ) multi.hs:1: Warning: No 'main' defined in module Main Overlapping instance declarations: multi.hs:9: Op_plus a MyInt multi.hs:12: Op_plus MyInt a Failed, modules loaded: none. Prelude> Thanks and regards, Razvan ME
instance Op_plus MyInt MyInt where instance (Num a) => Op_plus a MyInt where instance (Num a) => Op_plus MyInt a where [..] Overlapping instance declarations: multi.hs:9: Op_plus a MyInt multi.hs:12: Op_plus MyInt a Failed, modules loaded: none.
The GHC manual talks about this at: http://haskell.cs.yale.edu/ghc/docs/latest/html/users_guide/type-extensions.... I think the issue is that GHC still requires that overlapping instances either do not unify, or have an instantiation ordering. Your 2nd and 3rd instances are unordered: 2 is an instance of 3, and 3 is an instance of 2. GHC doesn't notice the first instance. I observe that the docs above say "Yell if this restriction bites you.", so I shall hand this over to the GHC developers to discuss further... --KW 8-)
Hi! Keith Wansbrough wrote:
instance Op_plus MyInt MyInt where instance (Num a) => Op_plus a MyInt where instance (Num a) => Op_plus MyInt a where
[..]
Overlapping instance declarations: multi.hs:9: Op_plus a MyInt multi.hs:12: Op_plus MyInt a Failed, modules loaded: none.
The GHC manual talks about this at:
http://haskell.cs.yale.edu/ghc/docs/latest/html/users_guide/type-extensions....
I think the issue is that GHC still requires that overlapping instances either do not unify, or have an instantiation ordering. Your 2nd and 3rd instances are unordered: 2 is an instance of 3, and 3 is an instance of 2. GHC doesn't notice the first instance.
As you mention that documentation, it says: GHC is also conservative about committing to an overlapping instance. For example: class C a where { op :: a -> a } instance C [Int] where ... instance C a => C [a] where ... f :: C b => [b] -> [b] f x = op x From the RHS of f we get the constraint C [b]. But GHC does not commit to the second instance declaration, because in a paricular call of f, b might be instantiate to Int, so the first instance declaration would be appropriate. So GHC rejects the program. If you add -fallow-incoherent-instances GHC will ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ instead silently pick the second instance, without complaining about the problem of subsequent instantiations. I tried -fallow-incoherent-instances but it only worked on that example even the two examples seems to be the same problem. Am I right? Obs: I'm working with a GHC version 5.04.2. Does it make sens to try the latest 6.0 one?
I observe that the docs above say "Yell if this restriction bites you.", so I shall hand this over to the GHC developers to discuss further...
Big 10x! :-) Should I further explain why do I need something like this? And if yes, where should I do this? -- Razvan ME
| instance (Num a) => Op_plus a MyInt where | i `plus` (MyInt b) = i + b Remember that b is of type Int, but you also say that i is of any Num type. This clashes, since + requires both if its arguments to hve the same types. /K
Hi! Koen Claessen wrote:
| instance (Num a) => Op_plus a MyInt where | i `plus` (MyInt b) = i + b
Remember that b is of type Int, but you also say that i is of any Num type. This clashes, since + requires both if its arguments to hve the same types.
You are right! I did't notice that error. Here is a version of the example free (if a remove the last instance compiles cleanly) of this mistake. data MyInt = MyInt Integer deriving Show class Op_plus a b where plus :: a -> b -> Integer instance Op_plus MyInt MyInt where (MyInt a) `plus` (MyInt b) = a + b instance (Integral a) => Op_plus a MyInt where i `plus` (MyInt b) = (toInteger i) + b Obs: perhaps MyInt should be now MyInteger. :-) -- Razvan ME
participants (3)
-
Keith Wansbrough -
Koen Claessen -
Razvan Musaloiu-E.