Skip to content

Instantly share code, notes, and snippets.

@dtchepak
Created July 11, 2012 02:46
Show Gist options
  • Save dtchepak/3087638 to your computer and use it in GitHub Desktop.
Save dtchepak/3087638 to your computer and use it in GitHub Desktop.
compose arbitrary number of functions (a->a)
-- Want :: [a -> a] -> a -> a
-- Emulates: an . … . a3 . a2 . a1
Prelude> let a = [reverse, (++ " world"), (++ "!")]
-- Given "olleh", it should:
-- * reverse it: "hello"
-- * append " world": "hello world"
-- * append "!": "hello world!"
Prelude> foldr ($) "olleh" a
"dlrow !hello"
Prelude> foldl (\acc x -> x acc) "olleh" a
"hello world!"
Prelude> import Data.Monoid
Prelude Data.Monoid> mconcat a "olleh"
"helloolleh worldolleh!"
Prelude Data.Monoid> let b = map Endo a
Prelude Data.Monoid> mconcat b `appEndo` "olleh"
"dlrow !hello"
Prelude Data.Monoid> let compose = flip (foldl (flip ($))) -- flip . foldl . flip $ ($)
Prelude Data.Monoid> :t compose
compose :: [c -> c] -> c -> c
Prelude Data.Monoid> compose a "olleh"
"hello world!"
-- Using foldMap Endo:
Prelude Data.Monoid> import Data.Foldable
Prelude Data.Monoid Data.Foldable> (foldMap Endo a) `appEndo` "olleh"
"dlrow !hello"
-- Using Dual . Endo to get the expected order:
Prelude Data.Monoid Data.Foldable> (getDual . foldMap (Dual . Endo) $ a) `appEndo` "olleh"
"hello world!"
Prelude Data.Monoid Data.Foldable> (appEndo .getDual . foldMap (Dual . Endo) $ a) "olleh"
"hello world!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment