never executed always true always false
    1 module HelVM.HelIO.Collections.MapList where
    2 
    3 import           HelVM.HelIO.Containers.LLIndexSafe
    4 import           HelVM.HelIO.Containers.LLInsertDef
    5 import           HelVM.HelIO.Control.Safe
    6 
    7 import           Control.Monad.Extra
    8 
    9 import           Data.Default
   10 
   11 import qualified Data.IntMap                        as IntMap
   12 import qualified Data.List.Index                    as List
   13 import qualified Data.ListLike                      as LL
   14 import qualified GHC.Exts                           as I (IsList (..))
   15 import qualified Text.Show
   16 
   17 -- | Construction
   18 mapListEmpty :: MapList a
   19 mapListEmpty = mapListFromList []
   20 
   21 mapListFromList :: [a] -> MapList a
   22 mapListFromList = fromIndexedList <$> List.indexed
   23 
   24 fromIndexedList :: IndexedList a -> MapList a
   25 fromIndexedList = fromIntMap <$> IntMap.fromList
   26 
   27 fromIntMap :: IntMap a -> MapList a
   28 fromIntMap = MapList
   29 
   30 -- | DeConstruction
   31 mapListToList :: Default a => MapList a -> [a]
   32 mapListToList = listFromDescList <$> toDescList
   33 
   34 toDescList :: MapList a -> IndexedList a
   35 toDescList = IntMap.toDescList <$> unMapList
   36 
   37 -- | Internal function
   38 listFromDescList :: Default a => IndexedList a -> [a]
   39 listFromDescList = loop act <$> ([] , ) where
   40   act :: Default a => AccWithIndexedList a -> Either (AccWithIndexedList a) [a]
   41   act (acc , []                        ) = Right acc
   42   act (acc , [(i , v)]                 ) = Right $ consDef i $ v : acc
   43   act (acc , (i1 , v1) : (i2 , v2) : l ) = Left (consDef (i1 - i2 - 1) $ v1 : acc , (i2 , v2) : l)
   44 
   45 consDef :: Default a => Key -> [a] -> [a]
   46 consDef i l = (check <$> compare i) 0 where
   47   check LT = error "MapList.consDef index is negative"
   48   check EQ = l
   49   check GT = consDef (i - 1) (def : l)
   50 
   51 -- | Types
   52 type AccWithIndexedList a = ([a] , IndexedList a)
   53 type Key = IntMap.Key
   54 type IndexedList a = [(Key , a)]
   55 type MapString = MapList Char
   56 
   57 newtype MapList a = MapList {unMapList :: IntMap a}
   58   deriving stock (Eq , Ord, Read)
   59   deriving newtype (Semigroup , Monoid)
   60 
   61 -- | Standard instances
   62 instance (Default a , Show a) => Show (MapList a) where
   63   show = show <$> I.toList
   64 
   65 instance IsString MapString where
   66   fromString = mapListFromList
   67 
   68 instance Default a => IsList (MapList a) where
   69   type (Item (MapList a)) = a
   70   toList      = mapListToList
   71   fromList    = mapListFromList
   72   fromListN n = mapListFromList <$> fromListN n
   73 
   74 -- | ListLike instances
   75 instance Default a => LL.FoldableLL (MapList a) a where
   76   foldl f b = IntMap.foldl f b <$> unMapList
   77   foldr f b = IntMap.foldr f b <$> unMapList
   78 
   79 -- | My instances
   80 instance {-# OVERLAPPING #-} IndexSafe (MapList a) a where
   81   findWithDefault e i = IntMap.findWithDefault e i <$> unMapList
   82   findMaybe    = mapListFindMaybe
   83   indexMaybe   = mapListIndexMaybe
   84   findSafe   i = liftMaybeOrError "MapList.findSafe: index is not correct" <$> mapListFindMaybe i
   85   indexSafe  l = liftMaybeOrError "MapList.LLIndexSafe: index is not correct" <$> mapListIndexMaybe l
   86 
   87 instance InsertDef (MapList a) a where
   88   insertDef i e = fromIntMap <$> IntMap.insert i e <$> unMapList
   89 
   90 -- | Internal functions
   91 mapListFindMaybe :: Key -> MapList a -> Maybe a
   92 mapListFindMaybe  i   = IntMap.lookup i <$> unMapList
   93 
   94 mapListIndexMaybe :: MapList a -> Key -> Maybe a
   95 mapListIndexMaybe l i = unMapList l IntMap.!? i