{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}

module Data.FuzzySet.Monad
  ( add
  , add_
  , findMin
  , values
  , addMany
  , addMany_
  , find
  , findOne
  , findOneMin
  , closestMatch
  , closestMatchMin
  , size
  , isEmpty
  , FuzzySearchT (..)
  , FuzzySearch
  , runFuzzySearchT
  , runDefaultFuzzySearchT
  , runFuzzySearch
  , runDefaultFuzzySearch
  , MonadFuzzySearch
  ) where

import Control.Monad (void)
import Control.Monad.Except (ExceptT)
import Control.Monad.Fix
import Control.Monad.Identity (Identity, runIdentity)
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Reader (ReaderT)
import Control.Monad.State (MonadState, StateT, evalStateT, gets)
import Control.Monad.Trans (MonadTrans, lift)
import Control.Monad.Trans.Cont (ContT)
import Control.Monad.Trans.Maybe (MaybeT)
import Control.Monad.Trans.Select (SelectT)
import Control.Monad.Writer (WriterT)
import Data.FuzzySet.Simple (FuzzySet, FuzzyMatch, emptySet)
import qualified Data.FuzzySet.Simple as Simple
import qualified Data.FuzzySet.Internal as FuzzySet
import Data.FuzzySet.Utils ((<$$$>), (<$$>))
import Data.Text (Text)

-- | FuzzySearch monad transformer
newtype FuzzySearchT m a = FuzzySearchT { forall (m :: * -> *) a. FuzzySearchT m a -> StateT FuzzySet m a
getFuzzySearchT :: StateT FuzzySet m a }
  deriving
    ( (forall a b. (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b)
-> (forall a b. a -> FuzzySearchT m b -> FuzzySearchT m a)
-> Functor (FuzzySearchT m)
forall a b. a -> FuzzySearchT m b -> FuzzySearchT m a
forall a b. (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
forall (m :: * -> *) a b.
Functor m =>
a -> FuzzySearchT m b -> FuzzySearchT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
fmap :: forall a b. (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> FuzzySearchT m b -> FuzzySearchT m a
<$ :: forall a b. a -> FuzzySearchT m b -> FuzzySearchT m a
Functor
    , Functor (FuzzySearchT m)
Functor (FuzzySearchT m) =>
(forall a. a -> FuzzySearchT m a)
-> (forall a b.
    FuzzySearchT m (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b)
-> (forall a b c.
    (a -> b -> c)
    -> FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m c)
-> (forall a b.
    FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b)
-> (forall a b.
    FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m a)
-> Applicative (FuzzySearchT m)
forall a. a -> FuzzySearchT m a
forall a b.
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m a
forall a b.
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
forall a b.
FuzzySearchT m (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
forall a b c.
(a -> b -> c)
-> FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m c
forall (m :: * -> *). Monad m => Functor (FuzzySearchT m)
forall (m :: * -> *) a. Monad m => a -> FuzzySearchT m a
forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m a
forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall (m :: * -> *) a. Monad m => a -> FuzzySearchT m a
pure :: forall a. a -> FuzzySearchT m a
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
<*> :: forall a b.
FuzzySearchT m (a -> b) -> FuzzySearchT m a -> FuzzySearchT m b
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m c
liftA2 :: forall a b c.
(a -> b -> c)
-> FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m c
$c*> :: forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
*> :: forall a b.
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
$c<* :: forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m a
<* :: forall a b.
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m a
Applicative
    , Applicative (FuzzySearchT m)
Applicative (FuzzySearchT m) =>
(forall a b.
 FuzzySearchT m a -> (a -> FuzzySearchT m b) -> FuzzySearchT m b)
-> (forall a b.
    FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b)
-> (forall a. a -> FuzzySearchT m a)
-> Monad (FuzzySearchT m)
forall a. a -> FuzzySearchT m a
forall a b.
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
forall a b.
FuzzySearchT m a -> (a -> FuzzySearchT m b) -> FuzzySearchT m b
forall (m :: * -> *). Monad m => Applicative (FuzzySearchT m)
forall (m :: * -> *) a. Monad m => a -> FuzzySearchT m a
forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> (a -> FuzzySearchT m b) -> FuzzySearchT m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> (a -> FuzzySearchT m b) -> FuzzySearchT m b
>>= :: forall a b.
FuzzySearchT m a -> (a -> FuzzySearchT m b) -> FuzzySearchT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
>> :: forall a b.
FuzzySearchT m a -> FuzzySearchT m b -> FuzzySearchT m b
$creturn :: forall (m :: * -> *) a. Monad m => a -> FuzzySearchT m a
return :: forall a. a -> FuzzySearchT m a
Monad
    , MonadState FuzzySet
    , Monad (FuzzySearchT m)
Monad (FuzzySearchT m) =>
(forall a. IO a -> FuzzySearchT m a) -> MonadIO (FuzzySearchT m)
forall a. IO a -> FuzzySearchT m a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
forall (m :: * -> *). MonadIO m => Monad (FuzzySearchT m)
forall (m :: * -> *) a. MonadIO m => IO a -> FuzzySearchT m a
$cliftIO :: forall (m :: * -> *) a. MonadIO m => IO a -> FuzzySearchT m a
liftIO :: forall a. IO a -> FuzzySearchT m a
MonadIO
    , Monad (FuzzySearchT m)
Monad (FuzzySearchT m) =>
(forall a. (a -> FuzzySearchT m a) -> FuzzySearchT m a)
-> MonadFix (FuzzySearchT m)
forall a. (a -> FuzzySearchT m a) -> FuzzySearchT m a
forall (m :: * -> *).
Monad m =>
(forall a. (a -> m a) -> m a) -> MonadFix m
forall (m :: * -> *). MonadFix m => Monad (FuzzySearchT m)
forall (m :: * -> *) a.
MonadFix m =>
(a -> FuzzySearchT m a) -> FuzzySearchT m a
$cmfix :: forall (m :: * -> *) a.
MonadFix m =>
(a -> FuzzySearchT m a) -> FuzzySearchT m a
mfix :: forall a. (a -> FuzzySearchT m a) -> FuzzySearchT m a
MonadFix
    )

-- | Evaluate a `FuzzySearchT` computation with the given options.
runFuzzySearchT :: (Monad m)
  => FuzzySearchT m a
  -> Int
  -- ^ Lower bound on gram sizes to use (inclusive)
  -> Int
  -- ^ Upper bound on gram sizes to use (inclusive)
  -> Bool
  -- ^ Whether or not to use the Levenshtein distance to determine the score
  -> m a
  -- ^ The result of running the computation in the inner monad
runFuzzySearchT :: forall (m :: * -> *) a.
Monad m =>
FuzzySearchT m a -> Int -> Int -> Bool -> m a
runFuzzySearchT FuzzySearchT m a
value = StateT FuzzySet m a -> FuzzySet -> m a
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT ( FuzzySearchT m a -> StateT FuzzySet m a
forall (m :: * -> *) a. FuzzySearchT m a -> StateT FuzzySet m a
getFuzzySearchT FuzzySearchT m a
value ) (FuzzySet -> m a)
-> (Int -> Int -> Bool -> FuzzySet) -> Int -> Int -> Bool -> m a
forall (f :: * -> *) (g :: * -> *) (h :: * -> *) a b.
(Functor f, Functor g, Functor h) =>
(a -> b) -> f (g (h a)) -> f (g (h b))
<$$$> Int -> Int -> Bool -> FuzzySet
emptySet

-- | Evaluate a `FuzzySearchT` computation with the following defaults:
--
--   * Gram size lower: @2@
--   * Gram size upper: @3@
--   * Use Levenshtein distance: @True@
runDefaultFuzzySearchT :: (Monad m) => FuzzySearchT m a -> m a
runDefaultFuzzySearchT :: forall (m :: * -> *) a. Monad m => FuzzySearchT m a -> m a
runDefaultFuzzySearchT FuzzySearchT m a
value = FuzzySearchT m a -> Int -> Int -> Bool -> m a
forall (m :: * -> *) a.
Monad m =>
FuzzySearchT m a -> Int -> Int -> Bool -> m a
runFuzzySearchT FuzzySearchT m a
value Int
2 Int
3 Bool
True

-- | FuzzySearch monad
type FuzzySearch = FuzzySearchT Identity

-- | Evaluate a `FuzzySearch` computation with the given options.
runFuzzySearch
  :: FuzzySearch a
  -> Int
  -- ^ Lower bound on gram sizes to use (inclusive)
  -> Int
  -- ^ Upper bound on gram sizes to use (inclusive)
  -> Bool
  -- ^ Whether or not to use the Levenshtein distance to determine the score
  -> a
  -- ^ The result of running the computation
runFuzzySearch :: forall a. FuzzySearch a -> Int -> Int -> Bool -> a
runFuzzySearch FuzzySearch a
value = Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a)
-> (Int -> Int -> Bool -> Identity a) -> Int -> Int -> Bool -> a
forall (f :: * -> *) (g :: * -> *) (h :: * -> *) a b.
(Functor f, Functor g, Functor h) =>
(a -> b) -> f (g (h a)) -> f (g (h b))
<$$$> FuzzySearch a -> Int -> Int -> Bool -> Identity a
forall (m :: * -> *) a.
Monad m =>
FuzzySearchT m a -> Int -> Int -> Bool -> m a
runFuzzySearchT FuzzySearch a
value

-- | Evaluate a `FuzzySearch` computation with the following defaults:
--
--   * Gram size lower: @2@
--   * Gram size upper: @3@
--   * Use Levenshtein distance: @True@
runDefaultFuzzySearch :: FuzzySearch a -> a
runDefaultFuzzySearch :: forall a. FuzzySearch a -> a
runDefaultFuzzySearch FuzzySearch a
value = FuzzySearch a -> Int -> Int -> Bool -> a
forall a. FuzzySearch a -> Int -> Int -> Bool -> a
runFuzzySearch FuzzySearch a
value Int
2 Int
3 Bool
True

class (MonadState FuzzySet m) => MonadFuzzySearch m where
  -- | Add a string to the set. A boolean is returned which is @True@ if the
  --   string was inserted, or @False@ if it already existed in the set.
  add     :: Text
          -- ^ The new entry
          -> m Bool
          -- ^ A flag to indicate whether the value was added (i.e., did not
          --   already exist in the set)
  -- | Try to match a string against the entries in the set, and return a list
  --   of all results with a score greater than or equal to the specified
  --   minimum score (i.e., the first argument). The results are ordered by
  --   similarity, with the closest match first.
  findMin :: Double
          -- ^ A minimum score
          -> Text
          -- ^ The string to search for
          -> m [FuzzyMatch]
          -- ^ A list of results (score and matched value)

instance MonadTrans FuzzySearchT where
  lift :: forall (m :: * -> *) a. Monad m => m a -> FuzzySearchT m a
lift = StateT FuzzySet m a -> FuzzySearchT m a
forall (m :: * -> *) a. StateT FuzzySet m a -> FuzzySearchT m a
FuzzySearchT (StateT FuzzySet m a -> FuzzySearchT m a)
-> (m a -> StateT FuzzySet m a) -> m a -> FuzzySearchT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> StateT FuzzySet m a
forall (m :: * -> *) a. Monad m => m a -> StateT FuzzySet m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift

instance (Monad m) => MonadFuzzySearch (FuzzySearchT m) where
  add :: Text -> FuzzySearchT m Bool
add     = Text -> FuzzySearchT m Bool
forall (m :: * -> *). MonadState FuzzySet m => Text -> m Bool
FuzzySet.add_
  findMin :: Double -> Text -> FuzzySearchT m [FuzzyMatch]
findMin = (FuzzySet -> [FuzzyMatch]) -> FuzzySearchT m [FuzzyMatch]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((FuzzySet -> [FuzzyMatch]) -> FuzzySearchT m [FuzzyMatch])
-> (Double -> Text -> FuzzySet -> [FuzzyMatch])
-> Double
-> Text
-> FuzzySearchT m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> FuzzySet -> [FuzzyMatch]
Simple.findMin

instance (MonadFuzzySearch m) => MonadFuzzySearch (StateT FuzzySet m) where
  add :: Text -> StateT FuzzySet m Bool
add     = m Bool -> StateT FuzzySet m Bool
forall (m :: * -> *) a. Monad m => m a -> StateT FuzzySet m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> StateT FuzzySet m Bool)
-> (Text -> m Bool) -> Text -> StateT FuzzySet m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> StateT FuzzySet m [FuzzyMatch]
findMin = m [FuzzyMatch] -> StateT FuzzySet m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> StateT FuzzySet m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> StateT FuzzySet m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> StateT FuzzySet m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

instance (MonadFuzzySearch m) => MonadFuzzySearch (ExceptT e m) where
  add :: Text -> ExceptT e m Bool
add     = m Bool -> ExceptT e m Bool
forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> ExceptT e m Bool)
-> (Text -> m Bool) -> Text -> ExceptT e m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> ExceptT e m [FuzzyMatch]
findMin = m [FuzzyMatch] -> ExceptT e m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> ExceptT e m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> ExceptT e m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

instance (MonadFuzzySearch m) => MonadFuzzySearch (ReaderT r m) where
  add :: Text -> ReaderT r m Bool
add     = m Bool -> ReaderT r m Bool
forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> ReaderT r m Bool)
-> (Text -> m Bool) -> Text -> ReaderT r m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> ReaderT r m [FuzzyMatch]
findMin = m [FuzzyMatch] -> ReaderT r m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> ReaderT r m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> ReaderT r m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

instance (MonadFuzzySearch m, Monoid w) => MonadFuzzySearch (WriterT w m) where
  add :: Text -> WriterT w m Bool
add     = m Bool -> WriterT w m Bool
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> WriterT w m Bool)
-> (Text -> m Bool) -> Text -> WriterT w m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> WriterT w m [FuzzyMatch]
findMin = m [FuzzyMatch] -> WriterT w m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> WriterT w m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> WriterT w m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

instance (MonadFuzzySearch m) => MonadFuzzySearch (MaybeT m) where
  add :: Text -> MaybeT m Bool
add     = m Bool -> MaybeT m Bool
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> MaybeT m Bool)
-> (Text -> m Bool) -> Text -> MaybeT m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> MaybeT m [FuzzyMatch]
findMin = m [FuzzyMatch] -> MaybeT m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> MaybeT m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> MaybeT m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

instance (MonadFuzzySearch m) => MonadFuzzySearch (ContT r m) where
  add :: Text -> ContT r m Bool
add     = m Bool -> ContT r m Bool
forall (m :: * -> *) a. Monad m => m a -> ContT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> ContT r m Bool)
-> (Text -> m Bool) -> Text -> ContT r m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> ContT r m [FuzzyMatch]
findMin = m [FuzzyMatch] -> ContT r m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> ContT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> ContT r m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> ContT r m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

instance (MonadFuzzySearch m, MonadState FuzzySet (SelectT s m)) => MonadFuzzySearch (SelectT s m) where
  add :: Text -> SelectT s m Bool
add     = m Bool -> SelectT s m Bool
forall (m :: * -> *) a. Monad m => m a -> SelectT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Bool -> SelectT s m Bool)
-> (Text -> m Bool) -> Text -> SelectT s m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add
  findMin :: Double -> Text -> SelectT s m [FuzzyMatch]
findMin = m [FuzzyMatch] -> SelectT s m [FuzzyMatch]
forall (m :: * -> *) a. Monad m => m a -> SelectT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [FuzzyMatch] -> SelectT s m [FuzzyMatch])
-> (Double -> Text -> m [FuzzyMatch])
-> Double
-> Text
-> SelectT s m [FuzzyMatch]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Double -> Text -> m [FuzzyMatch]
forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m [FuzzyMatch]
findMin

-- | Add a string to the set, or do nothing if a key that matches the string
--   already exists.
--
-- This function is identical to 'add', except that the latter returns a
-- boolean to indicate whether any new value was added.
add_ :: (MonadFuzzySearch m) => Text -> m ()
add_ :: forall (m :: * -> *). MonadFuzzySearch m => Text -> m ()
add_ = m Bool -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m Bool -> m ()) -> (Text -> m Bool) -> Text -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m Bool
forall (m :: * -> *). MonadFuzzySearch m => Text -> m Bool
add

-- | Add a list of strings to the set, all at once.
--
-- Unless you need to know the subset of values that were actually inserted,
-- use 'addMany_' instead.
addMany :: (MonadFuzzySearch m)
  => [Text]
  -- ^ A list of strings to add to the set
  -> m [Text]
  -- ^ A list of values that were inserted
addMany :: forall (m :: * -> *). MonadFuzzySearch m => [Text] -> m [Text]
addMany = [Text] -> m [Text]
forall (m :: * -> *). MonadState FuzzySet m => [Text] -> m [Text]
FuzzySet.addMany_

-- | Add a list of strings to the set, all at once.
--
-- This function is identical to 'addMany', except that the latter returns a
-- list of all values that were inserted.
addMany_ :: (MonadFuzzySearch m)
  => [Text]
  -- ^ A list of strings to add to the set
  -> m ()
addMany_ :: forall (m :: * -> *). MonadFuzzySearch m => [Text] -> m ()
addMany_ = m [Text] -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m [Text] -> m ()) -> ([Text] -> m [Text]) -> [Text] -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> m [Text]
forall (m :: * -> *). MonadFuzzySearch m => [Text] -> m [Text]
addMany

-- | Try to match the given string against the entries in the set, using a
--   minimum score of 0.33. Return a list of results ordered by similarity
--   score, with the closest match first. Use 'findMin' if you need to specify
--   a custom threshold value.
find :: (MonadFuzzySearch m)
  => Text
  -- ^ The string to search for
  -> m [FuzzyMatch]
  -- ^ A list of results (score and matched value)
find :: forall (m :: * -> *). MonadFuzzySearch m => Text -> m [FuzzyMatch]
find Text
str = (FuzzySet -> [FuzzyMatch]) -> m [FuzzyMatch]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (Text -> FuzzySet -> [FuzzyMatch]
Simple.find Text
str)

-- | Try to match the given string against the entries in the set using the
--   specified minimum score and return the closest match, if one is found.
findOneMin :: (MonadFuzzySearch m)
  => Double
  -- ^ A minimum score
  -> Text
  -- ^ The string to search for
  -> m (Maybe FuzzyMatch)
  -- ^ The closest match, if one is found
findOneMin :: forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m (Maybe FuzzyMatch)
findOneMin Double
minScore Text
str = (FuzzySet -> Maybe FuzzyMatch) -> m (Maybe FuzzyMatch)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (Double -> Text -> FuzzySet -> Maybe FuzzyMatch
Simple.findOneMin Double
minScore Text
str)

-- | Try to match the given string against the entries in the set, and return
--   the closest match, if one is found. A minimum score of 0.33 is used. To
--   specify a custom threshold value, instead use 'findOneMin'.
findOne :: (MonadFuzzySearch m)
  => Text
  -- ^ The string to search for
  -> m (Maybe FuzzyMatch)
  -- ^ The closest match, if one is found
findOne :: forall (m :: * -> *).
MonadFuzzySearch m =>
Text -> m (Maybe FuzzyMatch)
findOne Text
str = (FuzzySet -> Maybe FuzzyMatch) -> m (Maybe FuzzyMatch)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (Text -> FuzzySet -> Maybe FuzzyMatch
Simple.findOne Text
str)

-- | Try to match the given string against the entries in the set using the
--   specified minimum score and return the string that most closely matches
--   the input, if a match is found.
closestMatchMin :: (MonadFuzzySearch m)
  => Double
  -- ^ A minimum score
  -> Text
  -- ^ The string to search for
  -> m (Maybe Text)
  -- ^ The string most closely matching the input, if a match is found
closestMatchMin :: forall (m :: * -> *).
MonadFuzzySearch m =>
Double -> Text -> m (Maybe Text)
closestMatchMin Double
minScore Text
str = (FuzzySet -> Maybe Text) -> m (Maybe Text)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (Double -> Text -> FuzzySet -> Maybe Text
Simple.closestMatchMin Double
minScore Text
str)

-- | Try to match the given string against the entries in the set, and return
--   the string that most closely matches the input, if a match is found. A
--   minimum score of 0.33 is used. To specify a custom threshold value,
--   instead use 'closestMatchMin'.
closestMatch :: (MonadFuzzySearch m)
  => Text
  -- ^ The string to search for
  -> m (Maybe Text)
  -- ^ The string most closely matching the input, if a match is found
closestMatch :: forall (m :: * -> *). MonadFuzzySearch m => Text -> m (Maybe Text)
closestMatch Text
str = (FuzzySet -> Maybe Text) -> m (Maybe Text)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (Text -> FuzzySet -> Maybe Text
Simple.closestMatch Text
str)

-- | Return the elements of the set. No particular order is guaranteed.
values :: (MonadFuzzySearch m) => m [Text]
values :: forall (m :: * -> *). MonadFuzzySearch m => m [Text]
values = (FuzzySet -> [Text]) -> m [Text]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets FuzzySet -> [Text]
Simple.values

-- | Return the number of entries in the set.
size :: (MonadFuzzySearch m) => m Int
size :: forall (m :: * -> *). MonadFuzzySearch m => m Int
size = [Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Text] -> Int) -> m [Text] -> m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m [Text]
forall (m :: * -> *). MonadFuzzySearch m => m [Text]
values

-- | Return a boolean indicating whether the set is empty.
isEmpty :: (MonadFuzzySearch m) => m Bool
isEmpty :: forall (m :: * -> *). MonadFuzzySearch m => m Bool
isEmpty = [Text] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([Text] -> Bool) -> m [Text] -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m [Text]
forall (m :: * -> *). MonadFuzzySearch m => m [Text]
values