If I could easily go change the underlying data types used, I could declare a Functor by rearranging the constructor parameters, but in my application that would be a lot of code reworking that I'd rather avoid, and I'm not sure that the change wouldn't raise a conflict somewhere else. In a sense, what I seem to want is a type-expression equivalent of 'flip'.
My question, then, is: am I overlooking anything here? Is there a way to declare a Functor without changing the underlying type and class definitions? (I do think I could do something with generics, but they don't seem to be beyond being very experimental at this time.)
Below are two blocks of code:
1. a distillation from my current application, including a partial exploration of using generics, and
2. a reworking of the underlying type to demonstrate (to myself, at least) how changing the type makes it possible to declare a Functor instance.
In each case, the type that I wish to be an instance of Functor is 'EntryT'.
(Test cases all run under Hugs, though I did use GHCi to debug the kinds.)
#g --
1. Functor definition for EntryT not achieved
[[ -- spike-functorkind.hs -- Can an arbitrary polymorphic type constructor be used -- as a basis for a functor?
-- Suppose I have some general structure that associates types
-- with some structure of those types:
class Trans a b c where
trans :: (b -> b2) -> a b c -> a b2 c
dummy :: a b c -> c b -- provides kind information about c-- and a data structure that maintains a value of the base type -- and the constructed type: data EntryT b c = ET b (c b)
type EntryTPair b = EntryT b Pair
instance (Show b) => Show (EntryTPair b) where
show (ET b1 b2) = "ET "++show b1++" "++show b2-- An instance of Trans might be a pair:
data Pair b = P b b
deriving Showinstance Functor Pair where
fmap f (P k1 k2) = P (f k1) (f k2)instance Trans EntryT k Pair
where
trans f (ET kv (P k1 k2)) = ET (f kv) (P (f k1) (f k2))-- tests
f a = (a,a)
p1 = P "a1" "b1" e1 = ET "1" p1
test1a = fmap f p1 test1b = trans f e1
-- Is there any way to declare EntryTPair to be an instance of -- Functor without re-writing the definition of class T or type Pair -- and their associated methods? -- As far as I can tell, I cannot because the kind of EntryT is wrong -- to be used in a Functor instance declaration.
---------------------------------------------------------------- -- On the other hand, it seems that something approaching the -- desired effect could be achieved using generics [1]: -- -- [1] http://research.microsoft.com/Users/simonpj/papers/hmap/ -- http://www.cs.vu.nl/Strafunski/gmap/ --
class Typeable a where
cast :: (Typeable a, Typeable b) => a -> Maybe bclass Term a where
gmapT :: (forall b. Term b => b -> b) -> a -> aeverywhere :: Term a => (forall b. Term b => b -> b) -> a -> a everywhere f t = f (gmapT (everywhere f) t)
instance (Trans EntryT k Pair, Term k) => Term (EntryT k Pair) where
gmapT f e = trans f e-- then use:
-- test2 = everywhere f e1
-- except this doesn't quite work because it requires -- f :: a->a -- rather than -- f :: a1->a2
-- so try something like: -- g :: String -> String -- g a = a ++ a -- test2 = everywhere (MkT g) e1 ]]
2. Functor definition for EntryT achieved by rearranging type constructor expression:
[[ -- spike-functorkind1.hs -- -- Can an arbitrary polymorphic type constructor be used -- as a basis for a functor? -- -- This is spike-functorkind.hs with the parameters to -- Trans re-arranged, to demonstrate that doing so does -- make a Functor definition possible
-- Suppose I have some general structure that associates types
-- with some structure of those types:
class Trans a b c where
trans :: (c -> c2) -> a b c -> a b c2
dummy :: a b c -> b c -- provides kind information about b-- and a data structure that maintains a value of the base type -- and the constructed type: data EntryT b c = ET c (b c)
type EntryTPair c = EntryT Pair c
instance (Show c) => Show (EntryTPair c) where
show (ET c1 c2) = "ET "++show c1++" "++show c2-- An instance of Trans might be a pair:
data Pair b = P b b
deriving Showinstance Functor Pair where
fmap f (P k1 k2) = P (f k1) (f k2)instance Trans EntryT Pair k where
trans f (ET kv (P k1 k2)) = ET (f kv) (P (f k1) (f k2))instance Functor (EntryT Pair) where
fmap f = trans f-- tests
f a = (a,a)
p1 = P "a1" "b1" e1 = ET "1" p1
test1a = fmap f p1 test1b = trans f e1 test1c = fmap f e1 ]]
------------------- Graham Klyne <[EMAIL PROTECTED]> PGP: 0FAA 69FF C083 000B A2E9 A131 01B9 1C7A DBCA CB5E
_______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
