-
-
Save tel/714a5ea2e015d918f135 to your computer and use it in GitHub Desktop.
Transducers with explicit local state
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# 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