diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2018-02-05 17:02:55 +0100 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2018-02-05 17:02:55 +0100 |
commit | 6d1f39826963890e9612b39f92843f134b6973f3 (patch) | |
tree | a613a5ff0b0b61a021a22cda7523e1d9aef9c9d9 | |
parent | 529d127667a366f306f975b3ed34e8a118f3cefc (diff) | |
download | incremental-dfsts-6d1f39826963890e9612b39f92843f134b6973f3.tar incremental-dfsts-6d1f39826963890e9612b39f92843f134b6973f3.tar.gz incremental-dfsts-6d1f39826963890e9612b39f92843f134b6973f3.tar.bz2 incremental-dfsts-6d1f39826963890e9612b39f92843f134b6973f3.tar.xz incremental-dfsts-6d1f39826963890e9612b39f92843f134b6973f3.zip |
Framework for DFST edit lens
-rw-r--r-- | edit-lens/src/Control/Edit.lhs | 8 | ||||
-rw-r--r-- | edit-lens/src/Data/String/DFST.hs | 25 | ||||
-rw-r--r-- | edit-lens/src/Data/String/DFST/Lens.lhs | 82 |
3 files changed, 102 insertions, 13 deletions
diff --git a/edit-lens/src/Control/Edit.lhs b/edit-lens/src/Control/Edit.lhs index 7be8db4..19fe336 100644 --- a/edit-lens/src/Control/Edit.lhs +++ b/edit-lens/src/Control/Edit.lhs | |||
@@ -1,7 +1,7 @@ | |||
1 | \begin{comment} | 1 | \begin{comment} |
2 | \begin{code} | 2 | \begin{code} |
3 | module Control.Edit | 3 | module Control.Edit |
4 | ( Module(..) | 4 | ( Module(..), apply' |
5 | ) where | 5 | ) where |
6 | \end{code} | 6 | \end{code} |
7 | \end{comment} | 7 | \end{comment} |
@@ -24,6 +24,8 @@ In Haskell charakterisieren wir Moduln über ihren Monoid, d.h. die Wahl des Mon | |||
24 | Eine Repräsentierung als Typklasse bietet sich an: | 24 | Eine Repräsentierung als Typklasse bietet sich an: |
25 | 25 | ||
26 | \begin{code} | 26 | \begin{code} |
27 | infix 5 `apply` | ||
28 | |||
27 | class Monoid m => Module m where | 29 | class Monoid m => Module m where |
28 | type Domain m :: * | 30 | type Domain m :: * |
29 | apply :: Domain m -> m -> Maybe (Domain m) | 31 | apply :: Domain m -> m -> Maybe (Domain m) |
@@ -37,6 +39,10 @@ class Monoid m => Module m where | |||
37 | -- ^ Calculate a representation of an element of 'Domain m' in 'Del m' | 39 | -- ^ Calculate a representation of an element of 'Domain m' in 'Del m' |
38 | -- | 40 | -- |
39 | -- prop> init `apply` divInit m = m | 41 | -- prop> init `apply` divInit m = m |
42 | |||
43 | infixl 5 `apply'` | ||
44 | apply' :: Module m => Maybe (Domain m) -> m -> Maybe (Domain m) | ||
45 | apply' md e = flip apply e =<< md | ||
40 | \end{code} | 46 | \end{code} |
41 | \end{defn} | 47 | \end{defn} |
42 | 48 | ||
diff --git a/edit-lens/src/Data/String/DFST.hs b/edit-lens/src/Data/String/DFST.hs index 8a22dd3..75ca1cd 100644 --- a/edit-lens/src/Data/String/DFST.hs +++ b/edit-lens/src/Data/String/DFST.hs | |||
@@ -8,7 +8,7 @@ Description: Deterministic finite state transducers | |||
8 | -} | 8 | -} |
9 | module Data.String.DFST | 9 | module Data.String.DFST |
10 | ( DFST(..) | 10 | ( DFST(..) |
11 | , runDFST | 11 | , runDFST, runDFST' |
12 | ) where | 12 | ) where |
13 | 13 | ||
14 | import Data.Map.Strict (Map, (!?)) | 14 | import Data.Map.Strict (Map, (!?)) |
@@ -17,6 +17,8 @@ import qualified Data.Map.Strict as Map | |||
17 | import Data.Set (Set) | 17 | import Data.Set (Set) |
18 | import qualified Data.Set as Set | 18 | import qualified Data.Set as Set |
19 | 19 | ||
20 | import Control.Monad | ||
21 | |||
20 | data DFST state = DFST | 22 | data DFST state = DFST |
21 | { stInitial :: state | 23 | { stInitial :: state |
22 | , stTransition :: Map (state, Char) (state, Maybe Char) | 24 | , stTransition :: Map (state, Char) (state, Maybe Char) |
@@ -25,14 +27,13 @@ data DFST state = DFST | |||
25 | } | 27 | } |
26 | 28 | ||
27 | runDFST :: forall state. Ord state => DFST state -> String -> Maybe String | 29 | runDFST :: forall state. Ord state => DFST state -> String -> Maybe String |
28 | runDFST DFST{..} str = ($ []) <$> go stInitial str id | 30 | runDFST dfst@DFST{..} str = let (finalState, str') = runDFST' dfst stInitial str id |
29 | where | 31 | in str' "" <$ guard (finalState `Set.member` stAccept) |
30 | go :: state -> String -> (String -> String) -> Maybe (String -> String) | 32 | |
31 | go st [] acc | 33 | runDFST' :: forall state. Ord state => DFST state -> state -> String -> (String -> String) -> (state, (String -> String)) |
32 | | st `Set.member` stAccept = Just acc | 34 | runDFST' _ st [] acc = (st, acc) |
33 | | otherwise = Nothing | 35 | runDFST' dfst@DFST{..} st (c:cs) acc |
34 | go st (c:cs) acc | 36 | | Just (st', mc') <- stTransition !? (st, c) |
35 | | Just (st', mc') <- stTransition !? (st, c) | 37 | = runDFST' dfst st' cs $ acc . maybe id (:) mc' |
36 | = go st' cs $ acc . maybe id (:) mc' | 38 | | otherwise |
37 | | otherwise | 39 | = runDFST' dfst st cs acc |
38 | = go st cs acc | ||
diff --git a/edit-lens/src/Data/String/DFST/Lens.lhs b/edit-lens/src/Data/String/DFST/Lens.lhs new file mode 100644 index 0000000..52c80d0 --- /dev/null +++ b/edit-lens/src/Data/String/DFST/Lens.lhs | |||
@@ -0,0 +1,82 @@ | |||
1 | \begin{code} | ||
2 | {-# LANGUAGE TupleSections | ||
3 | #-} | ||
4 | |||
5 | module Data.String.DFST.Lens | ||
6 | ( | ||
7 | ) where | ||
8 | |||
9 | import Data.String.DFST | ||
10 | import Control.Lens.Edit | ||
11 | import Control.Edit | ||
12 | |||
13 | import Numeric.Natural | ||
14 | import Data.Sequence (Seq((:<|), (:|>))) | ||
15 | import qualified Data.Sequence as Seq | ||
16 | |||
17 | data StringEdit = Insert Natural Char | ||
18 | | Delete Natural | ||
19 | deriving (Eq, Ord, Show, Read) | ||
20 | |||
21 | data StringEdits = StringEdits (Seq StringEdit) | ||
22 | | SEFail | ||
23 | deriving (Eq, Ord, Show, Read) | ||
24 | |||
25 | insert :: Natural -> Char -> StringEdits | ||
26 | insert n c = StringEdits . Seq.singleton $ Insert n c | ||
27 | |||
28 | delete :: Natural -> StringEdits | ||
29 | delete n = StringEdits . Seq.singleton $ Delete n | ||
30 | |||
31 | instance Monoid StringEdits where | ||
32 | mempty = StringEdits Seq.empty | ||
33 | SEFail `mappend` _ = SEFail | ||
34 | _ `mappend` SEFail = SEFail | ||
35 | (StringEdits Seq.Empty) `mappend` x = x | ||
36 | x `mappend` (StringEdits Seq.Empty) = x | ||
37 | (StringEdits x@(bs :|> b)) `mappend` (StringEdits y@(a :<| as)) | ||
38 | | (Insert n _) <- a | ||
39 | , (Delete n') <- b | ||
40 | , n == n' | ||
41 | = StringEdits bs `mappend` StringEdits as | ||
42 | | otherwise = StringEdits $ x `mappend` y | ||
43 | |||
44 | instance Module StringEdits where | ||
45 | type Domain StringEdits = String | ||
46 | apply str SEFail = Nothing | ||
47 | apply str (StringEdits Seq.Empty) = Just str | ||
48 | apply str (StringEdits (es :|> Insert n c)) = (flip apply) (StringEdits es) =<< go str n c | ||
49 | where | ||
50 | go [] n c | ||
51 | | n == 0 = Just [c] | ||
52 | | otherwise = Nothing | ||
53 | go str@(x:xs) n c | ||
54 | | n == 0 = Just $ c : str | ||
55 | | otherwise = (x:) <$> go xs (pred n) c | ||
56 | apply str (StringEdits (es :|> Delete n)) = (flip apply) (StringEdits es) =<< go str n | ||
57 | where | ||
58 | go [] _ = Nothing | ||
59 | go (x:xs) n | ||
60 | | n == 0 = Just xs | ||
61 | | otherwise = (x:) <$> go xs (pred n) | ||
62 | |||
63 | init = "" | ||
64 | divInit = StringEdits . Seq.unfoldl go . (0,) | ||
65 | where | ||
66 | go (_, []) = Nothing | ||
67 | go (n, (c:cs)) = Just ((succ n, cs), Insert n c) | ||
68 | |||
69 | data DFSTAction state = DFSTBranch (Map state (state, String)) (DFSTAction state) (DFSTAction state) | ||
70 | | DFSTLeaf | ||
71 | |||
72 | dfstLens :: forall state. Ord state => DFST state -> EditLens (DFSTAction state) StringEdits StringEdits | ||
73 | dfstLens DFST{..} = EditLens ground propR propL | ||
74 | where | ||
75 | ground :: DFSTAction state | ||
76 | ground = DFSTLeaf | ||
77 | |||
78 | propR :: (DFSTAction state, StringEdits) -> (DFSTAction state, StringEdits) | ||
79 | propR = undefined | ||
80 | propL :: (DFSTAction state, StringEdits) -> (DFSTAction state, StringEdits) | ||
81 | propL = undefined | ||
82 | \end{code} | ||