
On Wed, Jan 27, 2016 at 9:41 AM, Imants Cekusins
Thank you Guillaume
fun deps are new for me too.
quoting from the above wiki link:
-- Read as: "container" type determines "elem" type. class Extract container elem | container -> elem where extract :: container -> elem The functional dependency "container -> elem" promises that we won't declare multiple instances with the same "container" type.
Without the functional dependency, both instances above would be allowed, and the type of v would be potentially ambiguous. Even if only one instance is defined, the type system will not figure it out without the functional dependency.
At first this is weird because we have the feeling that `instance Indexable (Tuple2 a b) a` fully qualifie the second type "a" as equivalent to the first subtype "a" of Tuple2. This is True for this instance, but the typechecker does not try to find one instance which match, it tries to find if , knowing the class definition, it is possible to be sure that there will only be one instance matching, and this is not the case because someone can easily define `instance Indexable (Tuple2 a b) String`. That's something I really like about this mecanism, is that adding new instances later cannot change the behavior of previous one. [A bit of digression] Actually, I don't know why, but at first though I always think in the wrong direction when reasoning about types. FunctionalDependencies is one example, but I had the same issue when I tried to understand why `fmap` cannot work on unboxed Vector. When reading the types, `fmap :: Functor f => (a -> b) -> f a -> f b`, I was understanding that it accepts any `a` as input. It was working on `Vector a`, but not on `Unbox a => Vector a` which appears more constrained, so if `fmap` was accepting any `a` as argument, it will certainly accept an `Unbox a` which is more constrained. But actually it works the opposite, `fmap` types means that `a` should be anything, and not something constrained.