summaryrefslogtreecommitdiff
path: root/edit-lens/src/Control/Edit/Container/Transducer.lhs
blob: 0173cc4555123252dfd9cebe8240480ebe284dc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
\begin{code}
{-# LANGUAGE TemplateHaskell #-}

module Control.Edit.Container.Transducer
  ( ContainerTransducer{..}, ctStates
  , runCT, stepCT
  ) where

import Control.Edit.Container
import Data.Map.Strict (Map, (!?))
import qualified Data.Map.Strict as Map
import Data.Set (Set)
import qualified Data.Set as Set

import Control.Monad.RWS.Strict
  
import Control.Monad.Writer.Class
import Control.Monad.Reader.Class
import Control.Monad.State.Class

import Control.Lens

import Data.Maybe


data ContainerTransducer state input output = ContainerTransducer
  { ctInitialState :: state
  , ctTransition :: Map (state, Content input) (ContainerEdits output, state)
    -- ^ States are stable (and produce no output) by default
  }

ctStates :: Ord state => ContainerTransducer state input output -> Set state
ctStates ContainerTransducer{..} = Map.foldrWithKey' (\(s1, _) (_, s2) -> Set.insert s1 . Set.insert s2) (Set.singleton ctInitialState) ctTransition

stepCT :: ( Ord state, Ord (Content input)
          , MonadReader (ContainerTransducer state input output) m
          , MonadState state m
          , MonadWriter (ContainerEdits output) m
          ) => Content input -> m ()
stepCT x = do
  ContainerTransducer{ ctTransition } <- ask
  state <- get
  let (output, newState) = fromMaybe (mempty, state) $ ctTransition !? (state, x)
  put newState
  tell output

runCT :: ( Ord state, Ord (Content input)
         , FoldableContainer input
         ) => ContainerTransducer state input output
           -> input
           -> ContainerEdits output
runCT ct@ContainerTransducer{ ctInitialState } input = runRWS (forMOf_ containerContent input stepCT) ct ctInitialState ^. _3
\end{code}

\begin{code}

data CTComplement state input output = CTComplement
  {
  }

-- Define edit-lens as span

\end{code}