{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Rg
( Rg(..)
, RgText(..)
, BE(..)
, Range
, newStartOfRangeFromList
, newStartOfRangeFromVector
, extractRange
) where
import Data.Array
import qualified Data.HashMap.Strict as HM
import Data.Maybe
import Data.Possibly
import qualified Data.Text as T
import qualified Data.Vector as V
import Fmt
class Rg rg where
sizeRg :: rg -> Int
toRg :: rg -> Int -> Maybe rg
fromRg :: rg -> Int
minRg :: rg -> rg
minRg = fromMaybe oops . flip toRg 0
where
oops = error "minRg: no minimum value in range"
maxRg :: rg -> rg
maxRg rg = fromMaybe oops $ toRg rg n
where
n = sizeRg rg - 1
oops = error "maxRg: no maximum value in range"
succRg :: rg -> Maybe rg
succRg rg = toRg rg $ fromRg rg + 1
predRg :: rg -> Maybe rg
predRg rg = toRg rg $ fromRg rg - 1
allListRg :: rg -> [rg]
allListRg rg = listRg rg [0..]
listRg :: rg -> [Int] -> [rg]
listRg rg is = catMaybes $ takeWhile isJust [ toRg rg i | i<-is ]
allVectorRg :: rg -> [rg]
allVectorRg rg = listRg rg [0..]
vectorRg :: rg -> [Int] -> V.Vector rg
vectorRg rg is = V.fromList $ listRg rg is
class (Rg e, Buildable e, Eq e, Ord e, Show e) => RgText e where
parseRgText :: e -> T.Text -> Possibly e
parseRgText e txt = maybe (Left msg) Right $ HM.lookup txt $ hashmap_t e
where
msg = "parseRgText: enumeration not recognised: "++show txt
newtype BE a = BE { _BE :: a }
deriving (Eq,Ord,Bounded,Enum,Show)
instance (Bounded i,Enum i) => Rg (BE i) where
sizeRg be = (1 +) $ fromEnum $ maxBound `asTypeOf` _BE be
toRg be i = case 0 <= i && i < sizeRg be of
True -> Just $ BE $ toEnum i
False -> Nothing
fromRg = fromEnum . _BE
data Range a =
Range
{ _rg_size :: Int
, _rg_elem :: Int
, _rg_array :: Array Int a
}
deriving (Show)
instance Rg (Range a) where
sizeRg = _rg_size
toRg rg i = case 0 <= i && i < _rg_size rg of
False -> Nothing
True -> Just rg { _rg_elem = i }
fromRg = _rg_elem
newStartOfRangeFromList :: [a] -> Range a
newStartOfRangeFromList xs =
Range
{ _rg_size = sz
, _rg_elem = 0
, _rg_array = listArray (0,sz-1) xs
}
where
sz = length xs
newStartOfRangeFromVector :: V.Vector a -> Range a
newStartOfRangeFromVector v =
Range
{ _rg_size = sz
, _rg_elem = 0
, _rg_array = listArray (0,sz-1) $ V.toList v
}
where
sz = V.length v
extractRange :: Range a -> a
extractRange Range{..} = _rg_array ! _rg_elem
hashmap_t :: RgText e => e -> HM.HashMap T.Text e
hashmap_t x = HM.fromList
[ (fmt $ build c,c)
| c <- allListRg x
]