
Learning from the example of "read" and also Real World Haskell, I come across the idea to overload my function's return types. Trying to think of an application for this, I've always wanted to write == applications like in Icon, that is a === b === c means a == b && b == c. This requires === to sense what context it is called in. If it's being called for a Boolean value, it needs to return a Boolean value. If it's being called as a parameter to another === application, then it needs to somehow remember both it's truthiness and if true what value its already seen. The idea is to eventually expand this to be able to write a >== b >== c ...but one thing at a time! My plan of attack is to write a typeclass: class Chain a b c where (==) :: a -> b -> c First check: Turned on -fglasgowexts to allow multiple parameters to typeclasses. Then write instances for the various contexts in which == might be applied. For boolean return values there are three instances: instance Eq a => Chain a a Bool ... example: 5 == 4 instance Eq a => Chain (Valid a) a Bool example: rightmost == in (5==4)==3 instance Eq a => Chain a (Valid a) Bool example: leftmost == in 5==(4==3) Sidebar: Valid is just an imitation of Maybe: data Valid a = Value a | Fail deriving (Show) But back to ==, the interesting part is the times when one senses we're in a context of comparing more values, for example, the left == in (x==y)==z. instance Eq a => Chain a a (Valid a) instance Eq a => Chain (Valid a) a (Valid a) instance Eq a => Chain a (Valid a) (Valid a) To test out this implementation I write a test function: test2 :: Eq a => a -> a -> Bool test2 a b = a === b and this works as expected. The problem comes when chainging the ===s together, I have to spoon-feed the compiler the inferred type: -- compiling this causes an error test3choke :: Eq a => a -> a -> a -> Bool test3choke a b c = a === b === c The error text: [1 of 1] Compiling ME ( ME.hs, interpreted ) ME.hs:63:19: Could not deduce (Chain a a c) from the context (Eq a) arising from use of `===' at ME.hs:63:19-25 Possible fix: add (Chain a a c) to the type signature(s) for `test3choke' In the first argument of `(===)', namely `a === b' In the expression: (a === b) === c In the definition of `test3choke': test3choke a b c = (a === b) === c ME.hs:63:19: Could not deduce (Chain c a Bool) from the context (Eq a) arising from use of `===' at ME.hs:63:19-31 Possible fix: add (Chain c a Bool) to the type signature(s) for `test3choke' or add an instance declaration for (Chain c a Bool) In the expression: (a === b) === c In the definition of `test3choke': test3choke a b c = (a === b) === c Failed, modules loaded: none. -- but spoon-feeding it the types will work test3Int :: Int -> Int -> Int -> Bool test3Int a b c = ((a === b) :: Valid Int) === c So it seems that the compiler is not doing instance inference the same way it does type inference. This is frustrating because the output of the parenthesiszed a === b can only be either of type Bool or Valid a, and the second argument of the outer === has to have the same type, which will force it to Valid a in most cases (Bool being an interesting exception). Is there some way to goad the compiler forward on this one, or is this the wrong approach altogether? Attachment: http://www.osaurus.us/~dm/tmp/ME.hs