
Am Dienstag, 4. November 2008 00:26 schrieb Michael Snoyman:
On Mon, Nov 3, 2008 at 2:55 PM, Daniel Fischer
wrote: class Multiplicable a b c where mult :: a -> b -> c
Use functional dependencies {-# LANGUAGE FunctionalDependencies #-},
class Multiplicable a b c | a b -> c where ...
which states that the result type of multiplication is determined by the argument types
or type families
That's exactly what I was looking for, thank you. Now that I got that working, I've noticed that it can be tedious making sure the arguments to sumProduct are in the correct order. Since multiplication is commutative, is there any way of automatically having the Multiplicable instances generate a "flip" mult?
Beware! Multiplication is usually not commutative, think about matrices. If (a `mult` b) and (b `mult` a) are both defined (need not be if they have different types), the products may have different types, so in general it is not desirable to have both defined automatically in a way that doesn't force you to supply the arguments in the correct order. In your case, you could provide instance Multiplicable MilesPerGallon Gallon Mile where mult = flip mult -- or write the implementation out and it should work whichever order the arguments are passed.
sumProduct :: (Addable c, Multiplicable a b c) => [a] -> [b] -> c
sumProduct x y = sum $ product x y
weightedAverage x y = (sumProduct y x) `divide` (sum y)
class Dividable a b c where divide :: c -> a -> b
FunDep here, too, but which one?
I did class Dividable a b c | c a -> b where...
Michael