haskellfunction-compositioncategory-theoryarrowscategory-abstractions

Control.Category, what does >>> and <<< mean?


I am following this blog, to write a simple http server in haskell,

Usage of >>> is not clear to me. What does this code snippet do?

handleHttpConnection r c = runKleisli
    (receiveRequest >>> handleRequest r >>> handleResponse) c >>
    close c

Similary on this link, i am seeing <<<

let h =     arr (++ "!")
          <<< arr foo
          <<< Kleisli bar
          <<< arr id

What does <<< and >>> do? (Hackage document is very concise and couldn't get much out of it.)


Solution

  • As Hackage and/or Hoogle will tell you,

    (>>>) :: Category k => a`k`b  -> b`k`c  -> a`k`c
    (<<<) :: Category k => b`k`c  -> a`k`b  -> a`k`c
    

    Observe that the latter is actually the same as

    (.)   :: Category k => b`k`c  -> a`k`b  -> a`k`c
    

    or, in its Prelude form, specialised to the Hask category of functions,

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

    So, <<< and >>> simply compose functions, or more generally morphisms/arrows.

    <<< composes in the same direction as the familiar ., while >>> flips the arguments so that “data flows from left to right”.


    Now, what arrow composition means, for categories other than Hask, depends of course on the category. Kleisli IO is an easy to understand example: say we have a pure function

    pipe :: Double -> String
    pipe = show . sqrt . (+2) . abs
    

    As I said, this can also be written

    pipe = abs >>> (+2) >>> sqrt >>> show
    

    Now, if you want to add primitive IO logging (like you might in an imperative language), you can introduce

    type (-|>) = Kleisli IO
    
    abs', add2', sqrt' :: Num a => a -|> a
    show' :: Show a => a -|> String
    
    abs'  = Kleisli $ \x -> do putStrLn ("Absolute of "++show x++"...")
                               return $ abs x
    add2' = Kleisli $ \x -> do putStrLn ("Add 2 to "++show x++"...")
                               return $ x + 2
    sqrt' = Kleisli $ \x -> do putStrLn ("Square root of "++show x++"...")
                               return $ sqrt x
    show' = Kleisli $ \x -> do putStrLn ("Show "++show x++"...")
                               return $ show x
    

    With that, you can define

    pipe' :: Double -|> String
    

    in exactly the same way as before, i.e.

    pipe' = abs' >>> add2' >>> sqrt' >>> show'
    

    But you'll now get the intermediate results printed out as a side-effect.