{-# LANGUAGE NamedFieldPuns #-} module Transducer ( Transducer , fromList , run ) where import Stream (Stream(..), merge) import qualified Stream (empty) import Graph (Graph(..), Vertex(..), Zipper(..), editLabel, follow, open, rewind, singleton, weave) type Transducer input output = Graph input [output] empty :: Transducer input output empty = open $ singleton [] add :: Ord input => Transducer input output -> ([input], output) -> Transducer input output add transducer (path, output) = rewind $ editLabel (weave transducer path) (output:) fromList :: Ord input => [([input], output)] -> Transducer input output fromList = foldl add empty run :: (Ord input, Eq output) => Transducer input output -> Stream input -> Stream output run transducer (Stream inputs) = foldl (\(Stream outputs) (input, stream) -> case follow transducer input of Nothing -> case context transducer of Top -> run (rewind transducer) stream _ -> Stream.empty Just newState@(Graph {focus}) -> Stream ((emit stream <$> label focus) ++ outputs) `merge` run newState stream ) Stream.empty inputs where emit stream output = (output, run (rewind transducer) stream)