Skip to content

Instantly share code, notes, and snippets.

@recursivecurry
Created December 5, 2015 12:21
Show Gist options
  • Save recursivecurry/7d7dfe6315b5c6dff1d0 to your computer and use it in GitHub Desktop.
Save recursivecurry/7d7dfe6315b5c6dff1d0 to your computer and use it in GitHub Desktop.
-- Understanding Clojure transducers through types
-- http://conscientiousprogrammer.com/blog/2014/08/07/understanding-cloure-transducers-through-types/
{-# LANGUAGE RankNTypes #-}
type Reducer a r = r -> a -> r
--type Transducer a b = Reducer a r -> Reducer b r
type Transducer a b = forall r . Reducer a r -> Reducer b r
--class Foldable f where
-- fold :: Transducer a (f a)
class Conjable f where
empty :: f a
conj :: Reducer a (f a)
--instance Foldable [] where
-- fold = foldl
instance Conjable [] where
empty = []
conj xs x = xs ++ [x]
--mapping :: (a -> b) -> (r -> b -> r) -> (r -> a -> r)
mapping :: (a -> b) -> Transducer b a
mapping f xf r a = xf r (f a)
filtering :: (a -> Bool) -> Transducer a a
filtering p xf r a = if p a then xf r a
else r
flatmapping :: Foldable f => (a -> f b) -> Transducer b a
flatmapping f xf r a = foldl xf r (f a)
--conj xs x = xs ++ [x]
--xlist :: ((r -> a -> r) -> (r -> b -> r)) -> [b] -> [a]
xlist:: (Foldable f, Conjable f) => Transducer a b -> f b -> f a
xlist xf = foldl (xf conj) empty
xmap :: (Foldable f, Conjable f) => (a -> b) -> f a -> f b
--xmap :: (a -> b) -> [a] -> [b]
xmap f = xlist $ mapping f
xfilter :: (Foldable f, Conjable f) => (a -> Bool) -> f a -> f a
xfilter p = xlist $ filtering p
xform :: Transducer Int Int
xform = mapping (+ 1) . filtering even . flatmapping (\x -> [0..x])
munge :: (Foldable f, Conjable f) => f Int -> f Int
munge = xlist xform
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment