This page may be out of date. Submit any pending changes before refreshing this page.
Hide this message.
Quora uses cookies to improve your experience. Read more

In Haskell (programming language), what are some practical uses of Kleisli composition (>=>)?

8 Answers
Sridhar Ramesh
Sridhar Ramesh, I Need a Job, in NYC or Remote-friendly.
Well, you can use bind to express all the same things that you can use Kleisli composition to express (and vice versa, at least given fmap; they're just different ways of picking "primitive" notions to define the concept of a monad).

(f >=> g) x = f x >>= g


In other words,
(f >=> g) x = do y <- f x
                 z <- g y
                 return z


Kleisli compostion is used for, well, composition... if you have one monadic function that takes in As and outputs Bs and another monadic function that takes in Bs and outputs Cs, and you want to chain them together, you use Kleisli composition.

As a very trivial example, suppose you had a function randomString :: Int -> IO String [which produces a random string of a given length], and another function print :: String -> IO () [which prints a string to the screen]. Their Kleisli composition would be the function (randomString >=> print) :: Int -> IO () [which produces a random string of a given length and prints it to the screen].
Bartosz Milewski
Bartosz Milewski, physicist gone functional programmer and mathematician

The use of Kleisli composition in monadic programming is the equivalent of point-free style.

Consider how regular functions are used. You can either apply a function to an argument or you can compose two functions directly. These two modes of programming are implemented using, respectively, the function-application operator and the composition operator:

($) :: (a->b) -> a -> b
(.) :: (b->c) -> (a->b) -> (a->c)

Monads let you compose functions with the signature [math](a->m b)[/math] (they are called Kleisli arrows). The two analogous operators are:

(=<<) :: (a->m b) -> m a -> m b
(<=<) :: (b->m c) -> (a->m b) -> (a->m c)

You can recognize these as the flipped versions of bind and the Kleisli composition (a.k.a., the “fish”).

In programming practice, function composition is not as common as function application. The use of function composition is characteristic of point-free style. Point free monadic computations are done using Kleisli composition.

Jeremy List
Jeremy List, Studied Haskell at university for 3 months, then in my spare time for 3 years.
An example: suppose I'm writing a game, and I've put it together as far as this function: gameStep :: GameState -> IO GameState
The easiest way to turn it into a loop would be: foldr1 (>=>) (repeat gameStep) startingState
Zach Conn
Zach Conn, Rice Mathematics '13, Software Engineer
Kleisli composition provides the morphisms in the Kleisli category of monadic functions associated to some given monad m. That is, it is the natural composition operator for functions of the type a -> m b, for some monad m.

Here's one of the simplest examples, which shows the Kleisli category in action for the list monad:

children :: Person -> [Person]
grandChildren = children <=< children
Kleisli composition is just composition for functions that need some extra plumbing to be hooked up together. For “monadic” functions of type (a -> m b), (b -> m c), (>=>) is simply a composition operator, just like (.) is the composition operator for “pure” functions of type (a ->b), (b -> c). (Note that (>=>) goes in the opposite direction as (.).)

The Category type class abstracts composition and identity away from functions into something more general. So, if you made a data type Kleisli to wrap a “monadic” function (a -> m b), then you could provide your own composition and identity:

newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
instance Monad m => Category (Kleisli m) where
  (Kleisli g) . (Kleisli f) = Kleisli $ f >=> g
  id = Kleisli return

prompt :: String -> IO String
prompt str = putStrLn str >> getLine

promptTwice :: String -> IO String
promptTwice = prompt >=> prompt

-- but we can also use our Kleisli Category:
kleisliPromptTwice :: Kleisli IO String String
kleisliPromptTwice = kleisliPrompt . kleisliPrompt
  where kleisliPrompt = Kleisli prompt
Sumant Tambe
Sumant Tambe, Sr. Software Engineer at LinkedIn
A practical use of Kleisli composition is the XPath language. It works more along the lines of Zach's answer. It is basically the list monad. Querying an XML document--a tree--is systematic composition of a->[b] functions. Only difference is that XPath is not typed. For typed XPath in C++ see LEESA.
Vlad Patryshev
Vlad Patryshev, Worked in Assemblers, Fortran, Cobol, Algol, Forth, C, C++, Java, Python.
In math, this so-called Kleisli composition is a usual composition, but in Kleisli category, that is, a category of functions with side effects. Kleisli composition combines side effects. Back in the original category, it's just a familiar flatmap.
Michael O. Church
Michael O. Church, studied at Carleton College
Use what works for you: do-notation, >>=, applicative operators (now that all Monads are Applicative). You don't have to use the Kleisli composition if it doesn't make sense for what you're trying to do.

What's great about Kleisli arrows is that (a) they capture the non-pure notion of "function" common to other languages while explicitly marking the "functionoids" (or, to use the proper term, arrows) as occurring in a monad and (b) give the monad laws a very clean, obvious presentation. Using Kleisli arrows, the monad laws become:

  1. f >=> return = f
  2. return >=> f = f
  3. f >=> (g >=> h) = (f >=> g) >=> h
In other words, they're just the identity (with return as the identity under (>=>)) and associativity properties that we've come to expect from a well-behaved algebraic structure like a Monoid.

Kleisli arrows also help one to group the symbols in a -> m b as a {-> m} b rather than the technically correct but opaque a -> {m b}. From this viewpoint, we come to see the relationship between this Monad (which is itself quite simple; it's just a type class) concept and the notion of "computational context". An a -> m b is like a a -> b but is allowed to do m-stuff. For a standalone m a, it's slightly trickier-- an a will never change but an m a like getChar :: IO Char can have a different value every time it's computed-- but one can think of it as isomorphic to () -> m a, a type signature that you rarely see in Haskell, but a valid one.