Skip to content

Instantly share code, notes, and snippets.

@tel
Last active August 29, 2015 14:06
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tel/714a5ea2e015d918f135 to your computer and use it in GitHub Desktop.
Save tel/714a5ea2e015d918f135 to your computer and use it in GitHub Desktop.
Transducers with explicit local state
{-# LANGUAGE GADTs, RankNTypes #-}
import Control.Applicative
import Control.Category
import Data.List (foldl')
import Data.Profunctor
import Prelude hiding ((.), id)
-- | Explicit state-passing Moore machine
data Moore i o where
Moore :: (i -> x -> x) -> x -> (x -> o) -> Moore i o
instance Profunctor Moore where
dimap f g (Moore ixx x xo) = Moore (ixx . f) x (g . xo)
instance Functor (Moore i) where fmap = rmap
-- | Strict pair since we'll be doing strict left folds
data Two a b = Two !a !b
instance Applicative (Moore i) where
pure = Moore (const id) () . const
Moore ixx x xf <*> Moore iyy y ya =
let izz i (Two x y) = Two (ixx i x) (iyy i y)
z = Two x y
zb (Two x y) = (xf x) (ya y)
in Moore izz z zb
--------------------------------------------------------------------------------
-- I'm ignoring early termination for now
newtype T a b = T (forall r . Moore b r -> Moore a r)
instance Profunctor T where
dimap f g (T t) = T (lmap f . t . lmap g)
instance Functor (T i) where fmap = rmap
instance Category T where
id = T id
T f . T g = T (g . f) -- composes the "right way" despite CPS
-- Is there an Arrow instance?
--------------------------------------------------------------------------------
tmap :: (a -> b) -> T a b
tmap f = T (lmap f)
tfilter :: (a -> Bool) -> T a a
tfilter p = T $ \(Moore axx x xr) ->
Moore (\a -> if p a then axx a else id) x xr
tflatMap :: (a -> [b]) -> T a b
tflatMap f = T $ \(Moore bxx x xr) ->
Moore (\a x -> foldl' (flip bxx) x (f a)) x xr
ttake :: Int -> T a a
ttake n = T $ \(Moore axx x xr) ->
let ayy a y@(Two x n)
| n > 0 = Two (axx a x) (n-1)
| otherwise = y
y = Two x n
yr (Two x _) = xr x
in Moore ayy y yr
-- Note that this generalizes
tseq :: T a b -> ([a] -> [b])
tseq (T t) as =
case t m of
Moore cons x xr ->
-- a way to feed the input
xr (foldl' (flip cons) x as)
where
-- a machine for executing the output
-- could easily be effectful
--
-- here we build lists "from the left" using
-- difference lists. This is probably the most
-- complex thing in this entire module
m = Moore (\a f -> f . (a:)) id ($ [])
data Three a b c = Three !a !b !c
tpartition :: Int -> T a [a]
tpartition n = T $ \(Moore asxx x xr) ->
-- the difference list trick would work here too
-- but I demonstrate the usual accumulate/reverse
-- mechanism instead
let ayy a (Three x m acc)
| m == 0 = Three (asxx (reverse acc) x) n []
| otherwise = Three x (m-1) (a:acc)
y = Three x n []
yr (Three x m acc) = xr x
in Moore ayy y yr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment