2021-01-02 09:09:38 +02:00
|
|
|
{-# LANGUAGE GADTs #-}
|
|
|
|
{-# LANGUAGE LambdaCase #-}
|
|
|
|
module Data.Query
|
|
|
|
(
|
2021-01-02 09:17:29 +02:00
|
|
|
-- * AST
|
|
|
|
Field(..)
|
|
|
|
|
2021-01-02 09:09:38 +02:00
|
|
|
-- * Combinators
|
2021-01-02 09:17:29 +02:00
|
|
|
, startsWith
|
2021-01-02 09:09:38 +02:00
|
|
|
, endsWith
|
2021-01-03 00:39:44 +02:00
|
|
|
, regex
|
2021-01-02 09:09:38 +02:00
|
|
|
, (.&&.)
|
|
|
|
|
|
|
|
-- * Evaluating queries
|
|
|
|
, evaluate
|
2021-01-03 00:39:44 +02:00
|
|
|
, predicate
|
2021-01-02 09:09:38 +02:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Data.Buuka
|
|
|
|
(BuukaEntry(..), URL(..))
|
|
|
|
|
|
|
|
import Data.List
|
|
|
|
(isPrefixOf, isSuffixOf)
|
|
|
|
|
2021-01-03 00:23:43 +02:00
|
|
|
import Text.Regex.TDFA
|
|
|
|
((=~))
|
|
|
|
|
2021-01-02 09:09:38 +02:00
|
|
|
import Data.Functor.Foldable
|
2021-01-03 00:39:44 +02:00
|
|
|
(Fix(..), cata)
|
2021-01-02 09:09:38 +02:00
|
|
|
|
|
|
|
data Field a where
|
|
|
|
Url :: Field String
|
|
|
|
Title :: Field String
|
|
|
|
|
2021-01-03 00:14:52 +02:00
|
|
|
data QueryF f where
|
2021-01-03 00:16:36 +02:00
|
|
|
StartsWith :: Field String -> String -> QueryF f
|
|
|
|
EndsWith :: Field String -> String -> QueryF f
|
2021-01-03 00:23:43 +02:00
|
|
|
Regex :: Field String -> String -> QueryF f
|
2021-01-03 00:14:52 +02:00
|
|
|
And :: f -> f -> QueryF f
|
2021-01-02 09:09:38 +02:00
|
|
|
|
|
|
|
deriving instance Functor QueryF
|
|
|
|
|
|
|
|
type Query = Fix QueryF
|
|
|
|
|
2021-01-03 00:16:36 +02:00
|
|
|
startsWith :: Field String -> String -> Query
|
2021-01-02 09:09:38 +02:00
|
|
|
startsWith field x = Fix (StartsWith field x)
|
|
|
|
|
2021-01-03 00:16:36 +02:00
|
|
|
endsWith :: Field String -> String -> Query
|
2021-01-02 09:09:38 +02:00
|
|
|
endsWith field x = Fix (EndsWith field x)
|
|
|
|
|
2021-01-03 00:39:44 +02:00
|
|
|
regex :: Field String -> String -> Query
|
|
|
|
regex field x = Fix (Regex field x)
|
|
|
|
|
2021-01-02 09:09:38 +02:00
|
|
|
(.&&.) :: Query -> Query -> Query
|
|
|
|
a .&&. b = Fix (And a b)
|
|
|
|
|
|
|
|
evaluate :: QueryF (BuukaEntry -> Bool) -> (BuukaEntry -> Bool)
|
|
|
|
evaluate = \case
|
|
|
|
StartsWith Url x -> \BuukaEntry{url=URL u} -> x `isPrefixOf` u
|
|
|
|
EndsWith Url x -> \BuukaEntry{url=URL u} -> x `isSuffixOf` u
|
|
|
|
StartsWith Title x -> \BuukaEntry{title=t} -> maybe False (x `isPrefixOf`) t
|
|
|
|
EndsWith Title x -> \BuukaEntry{title=t} -> maybe False (x `isSuffixOf`) t
|
2021-01-03 00:23:43 +02:00
|
|
|
Regex Url x -> \BuukaEntry{url=URL u} -> u =~ x
|
|
|
|
Regex Title x -> \BuukaEntry{title=t} -> maybe False (=~ x) t
|
2021-01-02 09:09:38 +02:00
|
|
|
And a b -> \e -> a e && b e
|
2021-01-03 00:39:44 +02:00
|
|
|
|
|
|
|
predicate :: Query -> BuukaEntry -> Bool
|
|
|
|
predicate = cata evaluate
|