Dan's example fails thus: | Map.hs:25:19: | Couldn't match expected type `Nest n1 f b' | against inferred type `Nest n1 f1 b' | In the expression: fmap (deepFMap n f) | In the definition of `deepFMap': | deepFMap (S n) f = fmap (deepFMap n f) | | for reasons I don't really understand. So I tried the following:
For what it's worth, here's why. Suppose we have type family N a :: * f :: forall a. N a -> Int f = <blah> g :: forall b. N b -> Int g x = 1 + f x The defn of 'g' fails with a very similar error to the one above. Here's why. We instantiate the occurrence of 'f' with an as-yet-unknown type 'alpha', so at the call site 'f' has type N alpha -> Int Now, we know from g's type sig that x :: N b. Since f is applies to x, we must have N alpha ~ N b Does that imply that (alpha ~ b)? Alas no! If t1=t2 then (N t1 = N t2), of course, but *not* vice versa. For example, suppose that type instance N [c] = N c Now we could solve the above with (alpha ~ [b]), or (alpha ~ [[b]]). You may say a) There is no such instance. Well, but you can see it pushes the search for a (unique) solution into new territory. b) It doesn't matter which solution the compiler chooses: any will do. True in this case, but false if f :: forall a. (Num a) => N a -> Int. Now it matters which instance is chosen. This kind of example encapsulates the biggest single difficulty with using type families in practice. What is worse is that THERE IS NO WORKAROUND. You *ought* to be able to add an annotation to guide the type checker. Currently you can't. The most obvious solution would be to allow the programmer to specify the types at which a polymorphic function is called, like this: g :: forall b. N b -> Int g x = 1 + f {b} x The {b} says that f takes a type argument 'b', which should be used to instantiate its polymorphic type variable 'a'. Being able to do this would be useful in other circumstances (eg impredicative polymorphism). The issue is really the syntax, and the order of type variables in an implicit forall. Anyway I hope this helps clarify the issue. Simon | -----Original Message----- | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-users- | boun...@haskell.org] On Behalf Of Dan Doel | Sent: 06 March 2009 03:08 | To: glasgow-haskell-users@haskell.org | Subject: Deep fmap with GADTs and type families. | | Greetings, | | Someone on comp.lang.functional was asking how to map through arbitrary | nestings of lists, so I thought I'd demonstrate how his non-working ML | function could actually be typed in GHC, like so: | | --- snip --- | | {-# LANGUAGE TypeFamilies, GADTs, EmptyDataDecls, | Rank2Types, ScopedTypeVariables #-} | | data Z | data S n | | data Nat n where | Z :: Nat Z | S :: Nat n -> Nat (S n) | | type family Nest n (f :: * -> *) a :: * | | type instance Nest Z f a = f a | type instance Nest (S n) f a = f (Nest n f a) | | deepMap :: Nat n -> (a -> b) -> Nest n [] a -> Nest n [] b | deepMap Z f = map f | deepMap (S n) f = map (deepMap n f) | | --- snip --- | | This works. However, the straight forward generalisation doesn't: | | --- snip --- | | deepFMap :: Functor f => Nat n -> (a -> b) -> Nest n f a -> Nest n f b | deepFMap Z f = fmap f | deepFMap (S n) f = fmap (deepFMap n f) | | --- snip --- | | This fails with a couple errors like: | | Map.hs:25:19: | Couldn't match expected type `Nest n1 f b' | against inferred type `Nest n1 f1 b' | In the expression: fmap (deepFMap n f) | In the definition of `deepFMap': | deepFMap (S n) f = fmap (deepFMap n f) | | for reasons I don't really understand. So I tried the following: | ...rest snipped...
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users