1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
-- |
-- Module : Foundation.Array.Indexed
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : portable
--
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE CPP #-}
#if MIN_VERSION_base(4,9,0)
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
#endif
module Foundation.Collection.Indexed
( IndexedCollection(..)
) where
import Basement.Compat.Base
import Basement.Numerical.Additive ((+))
import Basement.Types.OffsetSize
import Foundation.Collection.Element
import qualified Data.List
import qualified Basement.Block as BLK
import qualified Basement.UArray as UV
import qualified Basement.BoxedArray as BA
import qualified Basement.Exception as A
import qualified Basement.String as S
#if MIN_VERSION_base(4,9,0)
import qualified Basement.Sized.Block as BLKN
import qualified Basement.Sized.List as LN
import Basement.Nat
#endif
-- | Collection of elements that can indexed by int
class IndexedCollection c where
(!) :: c -> Offset (Element c) -> Maybe (Element c)
findIndex :: (Element c -> Bool) -> c -> Maybe (Offset (Element c))
instance IndexedCollection [a] where
(!) l (Offset n)
| n < 0 = Nothing
| otherwise = case Data.List.drop n l of
[] -> Nothing
x:_ -> Just x
findIndex predicate = fmap Offset . Data.List.findIndex predicate
instance UV.PrimType ty => IndexedCollection (BLK.Block ty) where
(!) l n
| A.isOutOfBound n (BLK.length l) = Nothing
| otherwise = Just $ BLK.index l n
findIndex predicate c = loop 0
where
!len = BLK.length c
loop i
| i .==# len = Nothing
| predicate (BLK.unsafeIndex c i) = Just i
| otherwise = loop (i + 1)
instance UV.PrimType ty => IndexedCollection (UV.UArray ty) where
(!) l n
| A.isOutOfBound n (UV.length l) = Nothing
| otherwise = Just $ UV.index l n
findIndex predicate c = loop 0
where
!len = UV.length c
loop i
| i .==# len = Nothing
| predicate (UV.unsafeIndex c i) = Just i
| otherwise = loop (i + 1)
instance IndexedCollection (BA.Array ty) where
(!) l n
| A.isOutOfBound n (BA.length l) = Nothing
| otherwise = Just $ BA.index l n
findIndex predicate c = loop 0
where
!len = BA.length c
loop i
| i .==# len = Nothing
| otherwise =
if predicate (BA.unsafeIndex c i) then Just i else loop (i + 1)
instance IndexedCollection S.String where
(!) = S.index
findIndex = S.findIndex
#if MIN_VERSION_base(4,9,0)
instance (NatWithinBound Int n, KnownNat n) => IndexedCollection (LN.ListN n a) where
(!) c off
| A.isOutOfBound off (LN.length c) = Nothing
| otherwise = Just $ LN.index c off
findIndex predicate c = loop 0
where
!len = LN.length c
loop i
| i .==# len = Nothing
| predicate (LN.index c i) = Just i
| otherwise = loop (i + 1)
instance (NatWithinBound (CountOf ty) n, KnownNat n, UV.PrimType ty) => IndexedCollection (BLKN.BlockN n ty) where
(!) c off
| A.isOutOfBound off (BLKN.length c) = Nothing
| otherwise = Just $ BLKN.index c off
findIndex predicate c = loop 0
where
!len = BLKN.length c
loop i
| i .==# len = Nothing
| predicate (BLKN.index c i) = Just i
| otherwise = loop (i + 1)
#endif
|