At Tue, 14 Jun 2011 12:31:47 -0400, Dan Doel wrote: > > Sorry about the double send, David. I forgot to switch to reply-all in > the gmail interface. > > Okay. I don't really write a lot of code like this, so maybe I missed > the quirks. > > In that case, HList has been relying on broken behavior of fundeps for > 7 years. :) Because the instance: > > instance TypeEq a b c > > violates the functional dependency, by declaring: > > instance TypeEq Int Int Int > instance TypeEq Int Int Char > instance TypeEq Int Int Double
No, these are not equivalent. The first one "TypeEq a b c" is just declaring an instance that works "forall c". The second is declaring multiple instances, which, if there were class methods, could have different code. The second one is illegal, because given just the first two types, a and b, you cannot tell which instance to pick. > class C a b | a -> b where > foo :: a -> b > foo = error "Yo dawg." > > instance C a b where > > bar :: Int > bar = foo "x" > > baz :: Char > baz = foo "x" > > so we're using an instance C String Int and an instance C String Char > despite the fact that there's a functional dependency from the first > argument to the second. A functional dependency such as "| a b -> c d" just guarantees that a and b uniquely determine the instance. Hence, it is okay to have class methods that do not mention type variables c and d, because the compiler will still know which instance to pick. Since your code only has one instance of class C, the unique instance is trivially guaranteed and the code is fine. In fact, your code is effectively the same as: class C a where foo :: a -> b foo = error "Yo dawg." instance C a where The same issues happen with type families. The following code is obviously illegal, because you have a duplicate instance of class C: class C a where type Foo a foo :: a -> Foo a foo = error "Yo dawg." instance C [Char] where type Foo [Char] = Int instance C [Char] where type Foo [Char] = Char On the other hand, though the compiler won't accept it, you could at least theoretically allow code such as the following: instance C [Char] where type Foo [Char] = forall b. () => b David _______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime