Reputation: 561
I am trying to reconcile the math notion of functor and the haskell notion of it. This article http://brianshourd.com/posts/2012-10-26-tilt-functors-in-haskell.html explains a bit, but maybe someone can provide an example for the following case:
Suppose i define the following categories
Add: where objects are 0,1,2,3,...., morphisms are (0+), (1+), (2+), ... (0+) is the id morph.
Mul: where objects are 0,1,2,3,...., morphisms are (0*), (1*), (2*), ... (1*) is the id morph.
The composition is (.)
How would one define a functor between these two categories in Haskell (if that is possible and if what i described above are categories at all)
Thank you
EDIT: As per @chi suggestion, i am clarifying the question a bit. I am more interested in how you would put/translate into Haskell any functor between these two categories (as opposed to the existence of one, for example map any number to 42 and any morphism to (1*) as @chi sugested)
EDIT 2: Another way to ask this is, how do you reconcile these two statements "the Functor typeclass, which is basically for things that can be mapped over" with "Given categories C and D, a functor F:C→D is a rule that assigns to each object A in C an object F(A) in D. It also assigns to every morphism f:A→B of objects of C a morphism F(f):F(A)→F(B)". If the type constructor [] (lists) is a functor, what are the two categories it connects and how exactly is it mapping objects and morphisms between those two categories
Upvotes: 0
Views: 329
Reputation: 10783
The issue is that Haskell's Functor
only represents a certain kind of functor: functors from the category of Haskell types and functions (Hask
) to itself. Functor
maps types to types (the objects of Hask
) and functions to functions (the morphisms of Hask
). For instance, the Maybe
Functor
maps any given type a
to the type Maybe a
and it uses fmap
to map a given function a -> b
to a function Maybe a -> Maybe b
.
In the category of Hask
, the objects are types and the morphisms are functions. Your category has integers as its objects and as a result doesn't fit the pattern of Functor
, so the question doesn't quite make sense to ask in this form, at least not with regard to the Functor
type class.
Upvotes: 2
Reputation: 5001
If you look at the definition of the class Category
in Haskell, you would see this.
class Category cat where
id :: cat a a
(.) :: cat b c -> cat a b -> cat a c
See, if the objects in the category are Int
s, then you would need to define those functions where a
, b
and c
are Int
s. This is fine when objects in the collection are types but not values. So you can't make them an instance of Category
.
Also looking at fmap
:
fmap :: (a -> b) -> f a -> f b
You can see it only makes sense with types (thus in the category Hask). If the objects are integers, you would pass morphisms like 4 --> 5
and ->
only works with types.
Then (0+)
is a morphism from Int
to Int
. You would need a morphism from, say, 2 to 5.
Maybe it would be something like this:
data IntMorphism = IdMorphism | IntMorphism Int Int
comp :: IntMorphism -> IntMorphism -> IntMorphism
comp IdMorphism m = m
comp m IdMorphism = m
comp (IntMorphism y' z) (IntMorphism x y)
| y /= y' = error "can't compose"
| otherwise = IntMorphism x z
f1 :: Int -> Int
f1 = (+5)
f2 :: IntMorphism -> IntMorphism
f2 IdMorphism = IdMorphism
f2 (IntMorphism x y) = IntMorphism (f1 x) (f1 y)
And the functor laws hold. In particular:
f2 (comp (IntMorphism y z) (IntMorphism x y))
= f2 (IntMorphism x z)
= IntMorphism (f1 x) (f1 z)
= comp (IntMorphism (f1 y) (f1 z)) (IntMorphism (f1 x) (f1 y))
= comp (f2 (IntMorphism y z)) (f2 (IntMorphism x y))
Of course, as it deals with values, it can't use the typeclasses defined in base and it is all done at runtime.
Upvotes: 1