module Control.Monad.Apiary.Filter.Internal.Strategy where
import Data.Apiary.SList
import Data.Maybe
import Data.Proxy
import Data.Reflection
class Strategy (w :: * -> *) where
type SNext w (as :: [*]) a :: [*]
readStrategy :: (v -> Maybe a)
-> ((k,v) -> Bool)
-> proxy (w a)
-> [(k, v)]
-> SList as
-> Maybe (SList (SNext w as a))
getQuery :: (v -> Maybe a) -> proxy (w a) -> ((k,v) -> Bool) -> [(k, v)] -> [Maybe a]
getQuery readf _ kf = map readf . map snd . filter kf
data Option a
instance Strategy Option where
type SNext Option as a = Snoc as (Maybe a)
readStrategy rf k p q l =
let rs = getQuery rf p k q
in if any isNothing rs
then Nothing
else Just . sSnoc l $ case catMaybes rs of
[] -> Nothing
a:_ -> Just a
data First a
instance Strategy First where
type SNext First as a = Snoc as a
readStrategy rf k p q l =
let rs = getQuery rf p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
a:_ -> Just $ sSnoc l a
data One a
instance Strategy One where
type SNext One as a = Snoc as a
readStrategy rf k p q l =
let rs = getQuery rf p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[a] -> Just $ sSnoc l a
_ -> Nothing
data Many a
instance Strategy Many where
type SNext Many as a = Snoc as [a]
readStrategy rf k p q l =
let rs = getQuery rf p k q
in if any isNothing rs
then Nothing
else Just $ sSnoc l (catMaybes rs)
data Some a
instance Strategy Some where
type SNext Some as a = Snoc as [a]
readStrategy rf k p q l =
let rs = getQuery rf p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
as -> Just $ sSnoc l as
data LimitSome u a
instance (Reifies u Int) => Strategy (LimitSome u) where
type SNext (LimitSome u) as a = Snoc as [a]
readStrategy rf k p q l =
let rs = take (reflectLimit p) $ getQuery rf p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
as -> Just $ sSnoc l as
reflectLimit :: Reifies n Int => proxy (LimitSome n a) -> Int
reflectLimit p = reflect $ asTyInt p
where
asTyInt :: proxy (LimitSome u a) -> Proxy u
asTyInt _ = Proxy
data Check a
instance Strategy Check where
type SNext Check as a = as
readStrategy rf k p q l =
let rs = getQuery rf p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
_ -> Just l
pOption :: Proxy a -> Proxy (Option a)
pOption _ = Proxy
pFirst :: Proxy a -> Proxy (First a)
pFirst _ = Proxy
pOne :: Proxy a -> Proxy (One a)
pOne _ = Proxy
pMany :: Proxy a -> Proxy (Many a)
pMany _ = Proxy
pSome :: Proxy a -> Proxy (Some a)
pSome _ = Proxy
pCheck :: Proxy a -> Proxy (Check a)
pCheck _ = Proxy