Functions of type foo :: f a -> g a

I would like to build a class that includes a method to move data from one arbitrary functor to another, a natural transformation. The structures might be more than just functors, but I can start with that. I ran into some practical issues with resolving the type variables for my multiparameter type class, which I can resolve with functional dependencies. I can also not isolate the natural transformation from my overall operation, muddling it with the element transformation. I was wondering if anyone had any words of advice, example or warning about this kind of function or method in general? Class (Functor f, Functor g) => Foo f g a where foo :: f a -> g a bar :: (a->b) -> g a -> g b Thanks, Gordon J. Uszkay, McMaster University uszkaygj@mcmaster.ca

On Tue, May 11, 2010 at 02:01:05PM -0400, Gordon J. Uszkay wrote:
I would like to build a class that includes a method to move data from one arbitrary functor to another, a natural transformation. The structures might be more than just functors, but I can start with that. I ran into some practical issues with resolving the type variables for my multiparameter type class, which I can resolve with functional dependencies. I can also not isolate the natural transformation from my overall operation, muddling it with the element transformation. I was wondering if anyone had any words of advice, example or warning about this kind of function or method in general?
Class (Functor f, Functor g) => Foo f g a where foo :: f a -> g a bar :: (a->b) -> g a -> g b
A couple points, * why is 'a' a member of the type class head? Functors don't care about what is stored inside the type, so your class shouldn't either if it is a transformer from functor to functor. * isn't bar exactly the same as 'fmap' for g? A better way might be class (Functor f, Functor g) => FunctorPair f g where transformFunctor :: f a -> g a though, I am not sure what your use is, there isn't an obvious instance to me, but I don't know what your motivating task is. John -- John Meacham - ⑆repetae.net⑆john⑈ - http://notanumber.net/

On Tue, May 11, 2010 at 2:06 PM, John Meacham
A better way might be
class (Functor f, Functor g) => FunctorPair f g where transformFunctor :: f a -> g a
though, I am not sure what your use is, there isn't an obvious instance to me, but I don't know what your motivating task is.
Furthermore, to select an instance at this point both Functors must be known in context of use, which exhausts pretty much the entire informational content of the instance--raising the question of what benefit is drawn from a type class at all, as opposed to simply passing around functions of type "f a -> g a" as needed. Consider that fmap doesn't require a multi-parameter type class for each pair a, b, it just takes a function (a -> b). The only way a type class would make sense here, I think, is with a fundep uniquely determining a particular natural transformation based on one of the Functors, at which point I'm not sure that the concept of "natural transformation" is what you're actually trying to model. - C.

On Tue, May 11, 2010 at 2:01 PM, Gordon J. Uszkay
I would like to build a class that includes a method to move data from one arbitrary functor to another, a natural transformation. The structures might be more than just functors, but I can start with that. I ran into some practical issues with resolving the type variables for my multiparameter type class, which I can resolve with functional dependencies. I can also not isolate the natural transformation from my overall operation, muddling it with the element transformation. I was wondering if anyone had any words of advice, example or warning about this kind of function or method in general?
Class (Functor f, Functor g) => Foo f g a where foo :: f a -> g a bar :: (a->b) -> g a -> g b
In general I would shy away from encoding natural transformations as a typeclass describing one family of morphisms of the form f a -> g a. I would avoid it because the choice of function f a -> g a isn't really canonical. There are many potentially valid such functions. foo :: Maybe a -> [a] foo (Just a) = [a] foo Nothing = [] bar :: Maybe a -> [a] bar (Just a) = repeat a bar Nothing = [] baz :: Maybe a -> [a] baz _ = Nothing quux n :: Int -> Maybe a -> [a] quux (Just a) = replicate a n quux Nothing = Nothing With that in mind an arguably better approach would be to define a natural transformation as: type Nat f g = forall a. f a -> g a or even type f :~> g = forall a. f a -> g a and pass them around explicitly then you can encode things like: hylohttp://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/...:: Functorhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Control-Mo...f => Algebrahttp://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/...g b -> (f :~>http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/...g) -> Coalgebrahttp://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/...f a -> a -> b hylo f e g = f . e . fmap (hylo f e g). g This is important because there can exist such natural transformations that need data out of your current environment: i.e. the natural transformation ((,) x), the quux example above, etc. -Edward Kmett
participants (4)
-
C. McCann
-
Edward Kmett
-
Gordon J. Uszkay
-
John Meacham