Hask is usually thought to be the category whose objects are types and morphisms are functions.
However, I've seen Conor McBride (#pigworker) warn against the use of Hask multiple times (1, 2, 3):
I would discourage talk of "the Hask Category" because it subconsciously conditions you against looking for other categorical structure in Haskell programming.
Note, I dislike the use of "Hask" as the name of the "category of Haskell types and functions": I fear that labelling one category as the Haskell category has the unfortunate side-effect of blinding us to the wealth of other categorical structure in Haskell programming. It's a trap.
I wish people wouldn't call it "Hask", though: it threatens to limit the imagination.
What other categories can we see in Haskell?
In one of his answers, he touches upon some of these ideas, but I wonder if someone could expand upon it; and I wonder if there are even more examples.
[...] there's a ton of categorical structure lurking everywhere, there's certainly a ton of categorical structure available (possibly but not necessarily) at higher kinds. I'm particularly fond of functors between indexed families of sets.
Constraints in Haskell also form a category. The objects are the constraints, and the arrows mean "this constraint implies this other constraint". So every constraint implies itself, and there's an arrow between Monad f and Applicative f, between Ord a and Eq a and between Ord a and Ord [a].
It is a thin category, so there is at most one arrow between two objects.
Gabriel Gonzalez has blogged about this. Here's one such post:
http://www.haskellforall.com/2012/08/the-category-design-pattern.html
In it, he calls Hask "the function category", and also discusses "the Kleisli category" and "the pipes category." These are all examples of instances of the Category typeclass in Haskell. The Category typeclass in Haskell is a subset of the categories you can find in Haskell.
I once uploaded an educational package that demonstrates one example of this. I called it MHask.
http://hackage.haskell.org/package/MHask
Copied from the hackage page:
MHask is the category where
The objects are Haskell types of kind (* → *) that have an instance of Prelude.Monad
An arrow from object m to object n is a Haskell function of the form (forall x. m x → n x)
Arrow composition is merely a specialization of Haskell function composition
The identity arrow for the object m is the Prelude.id function in Haskell, specialized to (forall x. m x → m x)
Caveat emptor; I have not looked at this in a long time. There may be mistakes.
Related
Consider a type class whose members are of type * -> *. For example: the Functor typeclass. It is a well-known fact that, in Haskell, there is a correspondence between this typeclass and its mathematical (i.e., Category Theoretic) analogue. Generalizing:
Question 1: Does every every typeclass in Haskell whose members are of kind * -> * correspond to some function between categories?
Now consider a typeclass whose members are of type *. For example, one could imagine a type class Group which corresponds to the category of Groups (technically, Group would be a subcategory of Hask whose objects comprise all of Haskell's types). Generalizing:
Question 2: Does every typeclass in Haskell whose members are of kind * correspond to some category (technically: some subcategory of Hask)?
From this, the next general question can be asked:
Question 3: Do typeclasses of kind equal to or higher than * -> * -> * correspond to some category theoretic notion?
And really, this entire question could be summarized as follows:
General Question: Does every Haskell type class correspond to some category theoretic notion?
EDIT: At the very least, it seems you could say that since every type class contains some set of Haskell types as its members, you could view every type class as some subcategory of Hask (closed under . and making use of id).
When interpreted sufficiently pedantically, the answer to all of these questions is "yes", but for uninformatively trivial reasons.
Every category C restricts to a discrete subcategory |C| with the same objects as C but only identity morphisms (and hence no interesting structure). At the very least, operations on Haskell types can be boringly interpreted as operations on the discrete category |*|. The recent "roles" story amounts to (but is not spun as) an attempt to acknowledge that the morphisms matter, not just the objects. The "nominal" role for types amounts to working in |*| rather than *.
(Note, I dislike the use of "Hask" as the name of the "category of Haskell types and functions": I fear that labelling one category as the Haskell category has the unfortunate side-effect of blinding us to the wealth of other categorical structure in Haskell programming. It's a trap.)
Being differently pedantic, I'd note that you can make up any old crap as a typeclass over any old kind, with no interesting structure whatsoever (but with trivial structure that can still be talked about categorically, if one must). However, the classes you find in the library are very often structure-rich. Classes over * -> * are often, by design, subclasses of Functor, requiring the existence of certain natural transformations in addition to fmap.
For question 2. Yes, of course a class over * gives a subcategory of *. It's no problem to chuck objects out of a category, because the categorical requirement that identities and composites exist require morphisms to exist, given objects, but make no demands about which objects exist. The fact that it's boringly possible makes it a boring fact. However, many Haskell typeclasses over * give rise to much more interesting categories than those arising just as subcategories of *. E.g., the Monoid class gives us a category where the objects are instances of Monoid and the arrows are monoid homomorphisms: not just any old function f from one Monoid to another, but one which preserves the structure: f mempty = mempty and f (mappend x y) = mappend (f x) (f y).
For question 3, well, in that there's a ton of categorical structure lurking everywhere, there's certainly a ton of categorical structure available (possibly but not necessarily) at higher kinds. I'm particularly fond of functors between indexed families of sets.
type (s :: k -> *) :-> (t :: k -> *) = forall x. s x -> t x
class FunctorIx (f :: (i -> *) -> (j -> *)) where
mapIx :: (s :-> t) -> (f s :-> f t)
When i and j coincide, it becomes sensible to ask when such an f is a monad. The usual categorical definition suffices, even though we've left * -> * behind.
The message is this: nothing about being a typeclass inherently induces interesting categorical structure; there is plenty of interesting categorical structure which can usefully be presented via type classes over all manner of kinds. There are most certainly interesting functors from * (sets and functions) to * -> * (functors and natural transformations). Don't be blinded by careless talk about "Hask" to the richness of categorical structure in Haskell.
One of the problems here is that category theory, a.k.a. general abstract nonsense, is a theory that you can use to talk about almost anything in mathematics. So everything that we are talking about can be expressed using the language of category theory, but we might not produce any interesting results.
Does every every typeclass in Haskell whose members are of kind * -> * correspond to some function between categories?
No. This question contains a type error! A function maps sets to sets, but a category is not a set. (Put another way, functions are morphisms in the category Set.) Categories are formulated using classes, often proper classes, so you cannot feed a category to a function.
We would call objects in * -> * morphisms in the category of Haskell types. A subcategory of this category is the category of functors between Haskell types, which is called Functor.
Does every typeclass in Haskell whose members are of kind * correspond to some category (technically: some subcategory of Hask)?
Yes. This is true, but it's not terribly interesting. Just remove every object from Hask that is not in your typeclass, and remove any morphism in Hask that does not consume and produce elements from your typeclass, and you are left with a subcategory of Hask. This category should have at least one object, ⊥, and at least one morphism, id.
Do typeclasses of kind equal to or higher than * -> * -> * correspond to some category theoretic notion?
Yes. Again, this won't be very interesting. Let's take a typeclass X with kind * -> * -> *.
Is X an object in a category of typeclasses with the same kind? Well, yes. But this category isn't very interesting, because it's hard to imagine any nontrivial morphisms.
Is X a morphism in some category? No, because it cannot be composed.
Is X a functor mapping a subcategory of types in Hask to a subcategory of morphisms on types in Hask? Sure, but we would have to have some special knowledge that both X Y a b and X Z a b are permissible for the same a b before we allow morphisms into our starting subcategory on types of Hask.
This doesn't seem to me like it will produce any useful insights, which is not really surprising because we don't really know anything about X.
Conclusions
Category theory is one of those tools that is really quite easy to overthink and overapply. If you are not interested in category theory as a subject of study in and of itself, my recommendation is to find concrete motivations to use it. Specific typeclasses (functors, lenses, monads, comonads, etc) will sometimes provide you with enough structure or "raw mathematical material" from which you can construct an interesting proof in category theory. But the study of typeclasses in general may be a bit more abstract than it is useful.
You can imagine mappings between categories that don't preserve their categorical structure. But they are not interesting. In category theory we want to work with structure-preserving mappings, and these are called functors.
A bare type constructor of the kind *->* has no provision for mapping morphisms. So the best you can do, as #pigworker explained, is to interpret them as functors from |C| to C, only because |C| has no nontrivial morphisms to be mapped.
Haskell Functor is an endofunctor, as long as it satisfies functor laws (which cannot be enforced in Haskell). An endofunctor is not an object in the category that it maps, therefore is not a type. But that's also true with morphisms -- they are not objects. There is, however, a way to represent morphisms as objects, if the category supports exponentials. Haskell's category of types is Cartesian closed, so it supports exponentials.
So does it also provide objects (types) representing endofunctors? As far as I know, it doesn't. So a functor is not a member of Hask (or whatever we call it).
Incidentally, a mapping of the kind *->*->* can have a nontrivial categorical interpretation as a bifunctor -- a structure-preserving functor from the product category CxC to C. See the definition of Bifunctor in Haskell.
I've been toying around in a Haskell for the past year or so and I'm actually starting to 'get' it, up until Monads, Lenses, Type Families, ... the lot.
I'm about to leave this comfort zone a little and I am moving to an OCaml project as a day job. Going through the syntax a little I was looking for similar higher level concepts, like for example functor.
I read the code in OCaml and the structure of a functor but I cannot seem to get whether they are now similar concepts in Haskell and OCaml or not.
In a nutshell, a functor in Haskell is for me mainly a way to lift functions in Haskell and I use it (and like it) like that.
In OCaml it gives me the feeling that it's closer to programming to an interface (for example when making a set or a list, with that compare function) and I wouldn't really know how to for example lift functions over the functor or so.
Can somebody explain me whether the two concepts are similar and if so what am I missing or not seeing? I googled around a bit and there doesn't seem to be a clear answer to be found.
Kasper
From a practical standpoint, you can think of "functors" in OCaml and Haskell as unrelated. As you said, in Haskell a functor is any type that allows you to map a function over it. In OCaml, a functor is a module parametrized by another module.
In Functional Programming, what is a functor? has a good description of what functors in the two languages are and how they differ.
However, as the name implies, there is actually a connection between the two seemingly disparate concepts! Both language's functors are just realizations of a concept from category theory.
Category theory is the study of categories, which are just arbitrary collections of objects with "morphisms" between them. The idea of a category is very abstract, so "objects" and "morphisms" can really be anything with a few restrictions—there has to be an identity morphism for every object and morphisms have to compose.
The most obvious example of a category is the category of sets and functions: the sets are the objects and the functions between sets the morphisms. Clearly, every set has has an identity function and functions can be composed. A very similar category can be formed by looking at a functional programming language like Haskell or OCaml: concrete types (e.g. types with kind *) are the objects and Haskell/OCaml functions are the morphisms between them.
In category theory, a functor is a transformation between categories. It is like a function between categories. When we're looking at the category of Haskell types, a functor is essentially a type-level function: it maps types to something else. The particular kind of functor we care about maps types to other types. A perfect example of this is Maybe: Maybe maps Int to Maybe Int, String to Maybe String and so on. It provides a mapping for every possible Haskell type.
Functors have one additional requirement—they have to map the category's morphisms as well as the objects. In particular, if we have a morphism A → B and our functor maps A to A' and B to B', it has to map the morphism A → B to some morphism A' → B'. As a concrete example, let's say we have the types Int and String. There are a whole bunch of Haskell functions Int → String. For Maybe to be a proper functor, it has to have a function Maybe Int → Maybe String for each of these.
Happily, this is exactly what the fmap function does—it maps functions. For Maybe, it has the type (a → b) → Maybe a → Maybe b; we can add some parentheses to get: (a → b) → (Maybe a → Maybe b). What this type signature tells us is that for any normal function we have, we also have a corresponding function over Maybes.
So a functor is a mapping between types that also preserves the functions between them. The fmap function is essentially just a proof of this second restriction on functors. This makes it easy to see how the Haskell Functor class is just a particular version of the mathematical concept.
So what about OCaml? In OCaml, a functor is not a type—it's a module. In particular, it's a parametrized module: a module that takes another module as an argument. Already, we can see some parallels: in Haskell, a Functor is like a type-level function; in OCaml, a functor is like a module-level function. So really, it's the same mathematical idea; however, instead of being used on types—like in Haskell—it's used on modules.
There's far more detail about how OCaml functors related to category theory functors on the CS site: What is the relation between functors in SML and Category theory?. The question talks about SML rather than OCaml per se, but my understanding is that the module system of OCaml is very closely related to that of SML.
In summary: functors in Haskell and in OCaml are two fundamentally different structures which both happen to be reifications of the same very abstract mathematical idea. I think it's pretty neat :).
Every time someone promises to "explain monads", my interest is piqued, only to be replaced by frustration when the alleged "explanation" is a long list of examples terminated by some off-hand remark that the "mathematical theory" behind the "esoteric ideas" is "too complicated to explain at this point".
Now I'm asking for the opposite. I have a solid grasp on category theory and I'm not afraid of diagram chasing, Yoneda's lemma or derived functors (and indeed on monads and adjunctions in the categorical sense).
Could someone give me a clear and concise definition of what a monad is in functional programming? The fewer examples the better: sometimes one clear concept says more than a hundred timid examples. Haskell would do nicely as a language for demonstration though I'm not picky.
This question has some good answers: Monads as adjunctions
More to the point, Derek Elkins' "Calculating Monads with Category Theory" article in TMR #13 should have the sort of constructions you're looking for: http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf
Finally, and perhaps this is really the closest to what you're looking for, you can go straight to the source and look at Moggi's seminal papers on the topic from 1988-91: http://www.disi.unige.it/person/MoggiE/publications.html
See in particular "Notions of computation and monads".
My own I'm sure too condensed/imprecise take:
Begin with a category Hask whose objects are Haskell types, and whose morphisms are functions. Functions are also objects in Hask, as are products. So Hask is Cartesian closed. Now introduce an arrow mapping every object in Hask to MHask which is a subset of the objects in Hask. Unit!
Next introduce an arrow mapping every arrow on Hask to an arrow on MHask. This gives us map, and makes MHask a covariant endofunctor. Now introduce an arrow mapping every object in MHask which is generated from an object in MHask (via unit) to the object in MHask which generates it. Join! And from the that, MHask is a monad (and a monoidal endofunctor to be more precise).
I'm sure there is a reason why the above is deficient, which is why I'd really direct you, if you're looking for formalism, to the Moggi papers in particular.
As a compliment to Carl's answer, a Monad in Haskell is (theoretically) this:
class Monad m where
join :: m (m a) -> m a
return :: a -> m a
fmap :: (a -> b) -> m a -> m b
Note that "bind" (>>=) can be defined as
x >>= f = join (fmap f x)
According to the Haskell Wiki
A monad in a category C is a triple (F : C → C, η : Id → F, μ : F ∘ F → F)
...with some axioms. For Haskell, fmap, return, and join line up with F, η, and μ, respectively. (fmap in Haskell defines a Functor). If I'm not mistaken, Scala calls these map, pure, and join respectively. (Scala calls bind "flatMap")
Ok, using Haskell terminology and examples...
A monad, in functional programming, is a composition pattern for data types with the kind * -> *.
class Monad (m :: * -> *) where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(There's more to the class than that in Haskell, but those are the important parts.)
A data type is a monad if it can implement that interface while satisfying three conditions in the implementation. These are the "monad laws", and I'll leave it to those long-winded explanations for the full explanation. I summarize the laws as "(>>= return) is an identity function, and (>>=) is associative." It's really not more than that, even if it can be expressed more precisely.
And that's all a monad is. If you can implement that interface while preserving those behavioral properties, you have a monad.
That explanation is probably shorter than you expected. That's because the monad interface really is very abstract. The incredible level of abstraction is part of why so many different things can be modeled as monads.
What's less obvious is that as abstract as the interface is, it allows generically modeling any control-flow pattern, regardless of the actual monad implementation. This is why the Control.Monad package in GHC's base library has combinators like when, forever, etc. And this is why the ability to explicitly abstract over any monad implementation is powerful, especially with support from a type system.
You should read the paper by Eugenio Moggi "Notions of computations and monads" which explain the then proposed role of monads to structure denotational semantic of effectful languages.
Also there is a related question:
References for learning the theory behind pure functional languages such as Haskell?
As you don't want hand-waving, you have to read scientific papers, not forum answers or tutorials.
A monad is a monoid in the category of endofunctors, whats the problem?.
Humor aside, I personally believe that monads, as they are used in Haskell and functional programming, are better understood from the monads-as-an-interface point of view (as in Carl's and Dan's answers) instead of from the monads-as-the-term-from-category-theory point of view. I have to confess that I only really internalized the whole monad thing when I had to use a monadic library from another language in a real project.
You mention that you didn't like all the "lots of examples" tutorials. Has anyone ever pointed you to the Awkward squad paper? It focuses manly in the IO monad but the introduction gives a good technical and historical explanation of why the monad concept was embraced by Haskell in the first place.
I don't really know what I'm talking about, but here's my take:
Monads are used to represent computations. You can think of a normal procedural program, which is basically a list of statements, as a bunch of composed computations. Monads are a generalization of this concept, allowing you to define how the statements get composed. Each computation has a value (it could just be ()); the monad just determines how the value strung through a series of computations behaves.
Do notation is really what makes this clear: it's basically a special sort of statement-based language that lets you define what happens between statements. It's as if you could define how ";" worked in C-like languages.
In this light all of the monads I've used so far makes sense: State doesn't affect the value but updates a second value which is passed along from computation to computation in the background; Maybe short-circuits the value if it ever encounters a Nothing; List lets you have a variable number of values passed through; IO lets you have impure values passed through in a safe way. The more specialized monads I've used like Gen and Parsec parsers are also similar.
Hopefully this is a clear explanation which isn't completely off-base.
Since you understand monads in the category-theoretic sense I am interpreting your question as being about the presentation of monads in functional programming.
Thus my answer avoids any explanation of what a monad is, or any intuition about its meaning or use.
Answer: In Haskell a monad is presented, in an internal language for some category, as the (internalised) maps of a Kleisli triple.
Explanation:
It is hard to be precise about the properties of the "Hask category", and these properties are largely irrelevant for understanding Haskell's presentation of monads.
Instead, for this discussion, it is more useful to understand Haskell as an internal language for some category C. Haskell functions define morphisms in C and Haskell types are objects in C, but the particular category in which these definitions are made is unimportant.
Parameteric data types, e.g. data F a = ..., are object mappings, e.g. F : |C| -> |C|.
The usual description of a monad in Haskell is in Kleisli triple (or Kleisli extension) form:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
where:
m is the object mapping m :|C| -> |C|
return is the unit operation on objects
>>= (pronounced "bind" by Haskellers) is the extension operation on morphisms but with its first two parameters swapped (cf. usual signature of extension (-)* : (a -> m b) -> m a -> m b)
(These maps are themselves internalised as families of morphisms in C, which is possible since m :|C| -> |C|).
Haskell's do-notation (if you have come across this) is therefore an internal language for Kleisli categories.
The Haskell wikibook page has a good basic explanation.
I am confused about using Functor
is Functor used for defining properties of mapping and how to write a mapping's properties in Haskell?
if so, can haskell be used to generate function or other things after definition written
Malformed head of type or class declaration: flow x y
import Control.Applicative
class flow x y where { f :: x y -> x; } // this line i do not know whether is enforced to write
// how to write this map
instance flow Int Int where
flow t flow(s, p) = flow(t+s, p)
flow 0 p = p
if there are more runnable example rather than the definition of the haskell, it would be better
when i replace properties in example found in google, usually can not run, or fragments
when use example about mapping, for example A -> B, there are data A data B defined first, but do not know why use data as a type defined, when i read category theory, there are arrows and objects
both are Hom, Functor is from Hom to Hom, does it mean data represent Hom?
When compare with software Singular, i become more confusing. Hom is a operation of kontraHom and Kohom and take two matrix.
Do Hom have different meaning in Haskell and Singular
Singular is a computer algebra system. Haskell is a programming language which computer algebra can be implemented within. You need to start simply and just learn basic Haskell syntax and concepts before trying to see the categorical/algebriac picture, especially since different elements can be implemented in different ways.
But let's try something simple to establish a common language. The notes I give here should be consistent with the treatment here: http://en.wikibooks.org/wiki/Haskell/Category_theory
One approach is to describe the category Hask. The objects of Hask are all Haskell types. Hask contains function types, as well as pairs, so it is cartesian closed, and all its arrows are isomorphic to objects. In categorical terms, a hom-set is the collection of all morphisms between two objects. So the hom-set on (Int,Float) is the collection of all functions that turn an Int into a Float.
Categorically, a functor between categories X and Y sends the objects of X to Y and the arrows of X to Y. It also therefore sends the hom-sets (collections of arrows) of X to Y.
The class Functor in Haskell provides part of what you get with a categorical functor. It provides an operation fmap that sends arrows on objects in Hask to arrows on some other category (which, in our case, must also be composed of some objects from Hask). It can send functions on values to functions on lists of values, or functions on values to functions on pairs which contain values, etc.
All that said, I would recommend learning Haskell without thinking about writing type classes or instances at all for some time. Stick to explicit data declarations and functions until you're more comfortable with the basic features of the language.
As an attempt at addressing the immediate confusion, a Haskell Functor defines a structure you can 'map' over, by specifying an implementation of 'fmap' (so yes, in Haskell you could use an instance of the Functor type class in order to specify an implementation of fmap for your specific structure)
Your provided code is problematic in two ways: i) A functor is already provided by Haskell (no need to redefine the class; instead you want to define an 'instance' of the Functor class), and ii) you need to adhere to the Functor interface.
Though I may suggest a more comprehensive resource (highly recommended is the book "Real World Haskell"), if you absolutely need to know more about how to deal with Haskell's instantiation of Functors, an excellent article is http://www.haskell.org/haskellwiki/Monads_as_containers
(every Monad is a Functor).
I'm a bit confused, and need someone to set me straight. Lets outline my current understanding:
Where E is an endofunctor, and A is some category:
E : A -> A.
Since all types and morphisms in Haskell are in the Hask category, is not any functor in Haskell also an endofunctor? F : Hask -> Hask.
I have a good feeling that I'm wrong, and oversimplifying this somehow, and I'd like someone to tell me what an idiot I am. Thanks.
You may want to clarify whether you're asking about "functors in Haskell", or Functors. It's not always clear what category is being assumed when Category Theory terms are used in Haskell.
But yes, the default assumption is Hask, which is taken to be the category of Haskell types with functions as morphisms. In that case, an endofunctor F on Hask would map any type A to a type F(A) and any function f between two types A and B to a function F(f) between some types F(A) and F(B).
If we then limit ourselves to only those endofunctors which map any type a to a type (f a) where f is a type constructor with kind * -> *, then we can describe the associated map for functions as a higher-order function with type (a -> b) -> (f a -> f b), which is of course the type class called Functor.
However, one can easily imagine well-behaved endofunctors on Hask which can't be written (directly) as an instance of Functor, such as a functor mapping a type a to Either a t. And while there's obviously not much sense in a functor from Hask to some other category entirely, it's reasonable to consider a (contravariant) functor from Hask to Haskop.
Beyond that, instances of Functor necessarily map from the entire category Hask onto some subset of it that, thus, also forms a category. But it's also reasonable to talk about functors between subsets of Hask. For instance, consider a functor that sends types Maybe a to [a].
You may wish to peruse the category-extras package, which provides some Category Theory-inspired structures embedded within Hask instead of assuming the entirety of it.
Even if ultimately, you manipulate Hask, there are a lot of other categories that can be built on Hask, which can be meaningful for the problem at hand:
Hask^op, which is Hask with all arrows reversed
Hask * Hask, functors on it are bifunctors
Comma categories, ie. objects are morphisms to a fixed object a, morphisms are commutative triangles
Functor categories, morphisms are natural transformations
Algebra categories
Monoidal categories
Kleisli categories
...
grab a copy of Mac Lane's Categories for the Working Mathematician to have definitions, and try to find by yourself the problem they solve in Haskell. Especially choke on adjoint functors (which are initial/terminal objects in the right category) and their relationship with monads.
You'll see that even if there is one big category (Hask, or perhaps "lifted objects from Hask with the right arrows/products/...", which encapsulates the language choices of Haskell such as non-strictness and lazyness), proper derived categories are expressive.
A possibly relevant (or at least interesting) discussion specifically regarding monads is found in the paper "Monads need not be endofunctors":
http://www.cs.nott.ac.uk/~txa/publ/Relative_Monads.pdf