Вопрос

Well, I am studying Haskell Monads. When I read the Wikibook Category theory article, I found that the signature of monad morphisms looks pretty like tautologies in logic, but you need to convert M a to ~~A, here ~ is the logic negation.

return :: a -> M a -- Map to tautology A => ~~A, double negation introduction
(>>=) :: M a -> (a -> M b) -> M b -- Map to tautology ~~A => (A => ~~B) => ~~B

the other operations is also tautologies:

fmap :: (a -> b) -> M a -> M b -- Map to (A => B) -> (~~A => ~~B)
join :: M (M a) -> M a -- Map to ~~(~~A) => ~~A

It's also understood that according to the fact that the Curry-Howard correspondence of normal functional languages is the intuitive logic, not classical logic, so we cannot expect a tautology like ~~A => A can have a correspondence.

But I am thinking of something else. Why the Monad can only relate to a double negation? what is the correspondence of single negation? This lead me to the following class definition:

class Nomad n where
    rfmap :: (a -> b) -> n b -> n a
    dneg :: a -> n (n a)

return :: Nomad n => a -> n (n a)
return = dneg
(>>=) :: Nomad n => n (n a) -> (a -> n (n b)) -> n (n b)
x >>= f = rfmap dneg $ rfmap (rfmap f) x

Here I defined a concept called "Nomad", and it supports two operations (both related to a logic axiom in intuitive logic). Notice the name "rfmap" means the fact that its signature is similar to functor's fmap, but the order of a and b are reversed in result. Now I can re-define the Monad operations with them, with replace M a to n (n a).

So now let's go to the question part. The fact that Monad is a concept from category theory seems to mean that my "Nomad" is also a category theory concept. So what is it? Is it useful? Are there any papers or research results exists in this topic?

Это было полезно?

Решение

Double negation is a particular monad

data Void --no constructor because it is uninhabited

newtype DN a = DN {runDN :: (a -> Void) -> Void}

instance Monad DN where
   return x = DN $ \f -> f x
   m >>= k  = DN $ \c -> runDN m (\a -> runDN (k a) c))

actually, this is an example of a more general monad

type DN = Cont Void
newtype Cont r a = Cont {runCont :: (a -> r) -> r}

which is the monad for continuation passing.

A concept like "monad" is not defined just by a signature, but also by some laws. So, here is a question, what should the laws for your construction be?

(a -> b) -> f b -> f a

is the signature of a method well known to category theory, the contravariant functor. It obeys essentially the same laws as functors (preserves (co)composition and identity). Actually, a contravariant functor is exactly a functor to the oppositite category. Since we are interested in "haskell functors" which are supposed to be endo-functors, we can see that a "haskell contravariant functor" is a functor Hask -> Hask_Op.

On the other hand, what about

a -> f (f a)

what laws should this have? I have a suggestion. In category theory, it is possible to map between Functors. Given two functors from F, G each from category C to category D, a natural transformation from F to G is a morphism in D

forall a. F a -> G a

that obeys certain coherence laws. You can do a lot with natural transformations, including using them to define a "functor category." But, the classic joke (due to Mac Lane) is that categories were invented to talk about functors, functors were invented to talk about natural transformations, and natural transformations were invented to talk about adjunctions.

A functor F : D -> C and a functor G : C -> D form an adjunction from C to D if there exist two natural transformations

unit : Id -> G . F
counit : F . G -> Id

This idea of an adjunction is a frequent way of understanding monads. Every adjunction gives rise to a monad in a totally natural way. That is, since the composition of these two functors is an endofunctor, and you have something akin to return (the unit), all you need is the join. But that is easy, join is just a function G . F . G . F -> G . F which you get by just using the counit "in the middle".

So, then with all this, what is it that you are looking for? Well

dneg :: a -> n (n a)

looks exactly like the unit of the adjunction of a contravariant functor with itself. Therefore, your Nomad type is likely (certainly if your use of it to construct a monad is correct) exactly the same as "a contravariant functor which is self adjoint." Searching for self adjoint functors will lead you back to Double-negation and Continuation passing...which is just where we started!


EDIT: Almost certainly some of the arrows above are backwards. The basic idea is right, though. You can work it out yourself using the citations below:

The best books on category theory are probably,

  • Steve Awodey, Category Theory
  • Sanders Mac Lane, Categories for the Working Mathematician

although numerous more approachable intro books exist including Benjamin Pierces book on Category Theory for computer scientists.

Video lectures online

A number of papers explore the adjunction angle on the continuation monad, for example

  • Hayo Thielecke, Continuation Semantics and Self-adjointness

The search terms "self adjoint", "continuation", and "monad" are good. Also, a number of bloggers have written about these issues. If you google "where do monads come from" you get useful results like this one from the n category cafe, or this one from sigfpe. Also Sjoerd Vissche's link to the Comonad reader.

Другие советы

That would be a self-adjoint contravariant functor. rfmap provides the contravariant functor part, and dneg is the unit and counit of the adjunction.

Op r is an example, which creates the continuation monad. See the contravariant modules in http://hackage.haskell.org/package/adjunctions for some code.

You should read http://comonad.com/reader/2011/monads-from-comonads/, which is related and very interesting.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top