module Data.DAWG
( DAWG (..)
, empty
, size
, insert
, lookup
, fromList
, fromLang
) where
import Prelude hiding (lookup)
import Control.Applicative ((<$>), (<*>))
import Data.List (foldl')
import Data.Binary (Binary, put, get)
import qualified Control.Monad.State.Strict as S
import Data.DAWG.Graph (Id, Node, Graph)
import qualified Data.DAWG.Graph as G
type GraphM a b = S.State (Graph a) b
mkState :: (Graph a -> Graph a) -> Graph a -> ((), Graph a)
mkState f g = ((), f g)
nodeBy :: Id -> GraphM a (Node a)
nodeBy i = G.nodeBy i <$> S.get
insertNode :: Ord a => Node a -> GraphM a Id
insertNode = S.state . G.insert
deleteNode :: Ord a => Node a -> GraphM a ()
deleteNode = S.state . mkState . G.delete
insertM :: Ord a => String -> a -> Id -> GraphM a Id
insertM [] y i = do
n <- nodeBy i
deleteNode n
insertNode (n { G.value = Just y })
insertM (x:xs) y i = do
n <- nodeBy i
j <- case G.onChar x n of
Just j -> return j
Nothing -> insertNode G.leaf
k <- insertM xs y j
deleteNode n
insertNode (G.subst x k n)
lookupM :: String -> Id -> GraphM a (Maybe a)
lookupM [] i = G.value <$> nodeBy i
lookupM (x:xs) i = do
n <- nodeBy i
case G.onChar x n of
Just j -> lookupM xs j
Nothing -> return Nothing
data DAWG a = DAWG
{ graph :: !(Graph a)
, root :: !Id }
deriving (Show, Eq, Ord)
instance (Binary a, Ord a) => Binary (DAWG a) where
put d = do
put (graph d)
put (root d)
get = DAWG <$> get <*> get
empty :: DAWG a
empty = DAWG G.empty 0
size :: DAWG a -> Int
size = G.size . graph
insert :: Ord a => String -> a -> DAWG a -> DAWG a
insert xs y d =
let (i, g) = S.runState (insertM xs y $ root d) (graph d)
in DAWG g i
lookup :: String -> DAWG a -> Maybe a
lookup xs d = S.evalState (lookupM xs $ root d) (graph d)
fromList :: (Ord a) => [(String, a)] -> DAWG a
fromList xs =
let update t (x, v) = insert x v t
in foldl' update empty xs
fromLang :: [String] -> DAWG ()
fromLang xs = fromList [(x, ()) | x <- xs]