module Test.Sloth.Pos
(
Pos, isRoot, root, first, rest, (|>), singleton,
bottom, PositionException(..),
bottomNoPos, NoPositionException(..),
mapWithPos
) where
import Data.List ( intersperse, isSuffixOf )
import Data.Data
import Control.Exception
infixl 5 |>
newtype Pos = Pos [Int]
deriving (Eq,Data,Typeable)
instance Show Pos where
showsPrec _ (Pos []) = showString "."
showsPrec _ (Pos ps) = intercalateS "." (map shows (reverse ps))
intercalateS :: String -> [ShowS] -> ShowS
intercalateS x = foldr (.) id . intersperse (showString x)
instance Ord Pos where
Pos p1 <= Pos p2 = p1 `isSuffixOf` p2
Pos p1 >= Pos p2 = p2 `isSuffixOf` p1
isRoot :: Pos -> Bool
isRoot (Pos l) = null l
root :: Pos
root = Pos []
first :: Pos -> Int
first (Pos ps) = last ps
rest :: Pos -> Pos
rest (Pos ps) = Pos (init ps)
(|>) :: Pos -> Int -> Pos
Pos ps |> p = Pos (p:ps)
singleton :: Int -> Pos
singleton = (root |>)
data PositionException = PositionException Pos
deriving (Typeable,Show)
instance Exception PositionException where
toException = SomeException
fromException (SomeException e) = cast e
data NoPositionException = NoPositionException
deriving (Typeable,Show)
instance Exception NoPositionException where
toException = SomeException
fromException (SomeException e) = cast e
bottom :: Pos -> a
bottom p = throw (PositionException p)
bottomNoPos :: a
bottomNoPos = throw NoPositionException
mapWithPos :: (Pos -> a -> b) -> Pos -> [a] -> [b]
mapWithPos f p = zipWith (\i x -> f (p|>i) x) [0..]