Search code examples
haskellcompositionmonoids

Piping data through a dynamic list of functions


So I often find myself designing 'pipeline' like flows of data, and oftentimes it ends up that the pipeline itself is dynamic.

Is there an easy way to do something like this?

pipe :: [a -> a] -> a -> a

Or is there a different pattern I should be reaching for with something like this? It's similar to the State monad, but I don't want to have to edit the functions to be (a -> (), a) or whatever :/

I realized that this is a monoid, so I wrote this, which seems like an elegant solution, does this exist in a library somewhere? It seems like most Arrow and Function Monoids do different things.

newtype Comp a = Comp { 
      runComp :: a -> a 
}

instance Monoid (Comp a) where
  (Comp a) `mappend` (Comp b) =  Comp (b . a)
  mempty = Comp id

pipe :: [a -> a] -> a -> a
pipe = runComp . foldMap Comp

Anyone have patterns that they use for this sort of thing? Thanks!


Solution

  • You're looking for one of

    foldr (.) id        -- right-to-left
    

    or

    foldl (flip (.)) id -- left-to-right
    

    depending on which order you want the functions composed:

    ghci> foldr (.) id [(+1),(*10)] 0
    1
    ghci> foldl (flip (.)) id [(+1),(*10)] 0
    10