{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}

module Talash.Internal ( -- * Search
                     SearchFunctions(..) , makeMatcher , lister , displayer ,  searchFunctionsFuzzy , searchFunctionsOL , searchWithMatcher
                     -- * Help for reading vectors
                   , readVectorStdIn , fileNamesSorted , readVectorHandle , readVectorHandleWith, emptyIndices
                     -- * Exports
                   , module Export ) where

import Control.Exception as Export (finally , catch, bracket , AsyncException)
import qualified Data.Text as T
import Data.Text.AhoCorasick.Automaton (CaseSensitivity (..))
import qualified Data.Text.IO as T
import Data.Vector (Vector , (!), force , generate , take, singleton , convert, enumFromN, unfoldr, unfoldrM , uniq , modify, concat)
import Data.Vector.Algorithms.Intro (sort)
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Sized as S
import GHC.Compact (Compact , compact , getCompact)
import GHC.TypeNats
import Intro hiding (sort, take , modify)
import Lens.Micro as Export (ASetter' , over, set, (^.) , _1 , _2 , _3 , (.~) , (?~) , (%~))
import Lens.Micro.TH as Export ( makeLenses )
import System.IO as Export ( Handle , hIsEOF , isEOF, hClose, stdin)
import Talash.Core hiding (makeMatcher)

data SearchFunctions a = SearchFunctions {
                           -- | Construct the matcher given the string to match.
                           SearchFunctions a -> Text -> Maybe (Matcher a)
_makeMatcher :: Text -> Maybe (Matcher a) ,
                           -- | Obtain the result for searching.
                           SearchFunctions a
-> forall (n :: Nat).
   KnownNat n =>
   MatcherSized n a
   -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n))
_lister :: forall n. KnownNat n => MatcherSized n a --  The n will be determined by the SomeMatcher constructed above
                                                                -> Vector Text --  The vector holding the candidates
                                                                -> U.Vector Int -- An unboxed vector of indices. Only these indices will be matched against the matcher
                                                                -> (U.Vector Int , U.Vector (Indices n)) ,
                           -- | Given the matcher @m@, the matched string @t@ and the indices of matches in @t@ divide @t@ in alternating strings that are a matches
                           --   and the gap between these matches. The first of these is always a gap and can be empty. The rest should be non empty.
                           SearchFunctions a
-> forall (n :: Nat).
   KnownNat n =>
   MatcherSized n a -> Text -> Vector n Int -> [Text]
_displayer :: forall n. KnownNat n => MatcherSized n a -> Text -> S.Vector n Int -> [Text] }
makeLenses ''SearchFunctions

emptyIndices :: Int -> U.Vector  (Indices 0)
emptyIndices :: Int -> Vector (Indices 0)
emptyIndices Int
n = Int -> (Int -> Indices 0) -> Vector (Indices 0)
forall a. Unbox a => Int -> (Int -> a) -> Vector a
U.generate Int
n ( , Vector 0 Int
forall a. Unbox a => Vector 0 a
S.empty)

-- | searchWithMatcher carries out one step of the search. Note that the search can stops before going through the whole vector of text. In that case the returned
--   vector of indices should contain not only the indices matched candidates but also the indices of candidates that weren't tested for a match.
searchWithMatcher :: SearchFunctions a -- ^ The configuration to use to carry out the search.
  -> Vector Text -- ^ The vector @v@ of candidates.
  -> Maybe Text -- ^ The query string
  -> U.Vector  Int -- ^ The subset of indices of @v@ to search against. If input changes from @talas@ to @talash@ we only search among candidates that matched @talas@.
  -> (U.Vector Int , (Int , Vector [Text])) -- ^ The indices of the matched candidates (see the note above) and the matched candidates broken up according to the match.
searchWithMatcher :: SearchFunctions a
-> Vector Text
-> Maybe Text
-> Vector Int
-> (Vector Int, (Int, Vector [Text]))
searchWithMatcher SearchFunctions a
fs Vector Text
v Maybe Text
t Vector Int
s = (Vector Int, (Int, Vector [Text]))
-> (Matcher a -> (Vector Int, (Int, Vector [Text])))
-> Maybe (Matcher a)
-> (Vector Int, (Int, Vector [Text]))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Vector Int, (Int, Vector [Text]))
nc Matcher a -> (Vector Int, (Int, Vector [Text]))
go ((SearchFunctions a
fs SearchFunctions a
-> Getting
     (Text -> Maybe (Matcher a))
     (SearchFunctions a)
     (Text -> Maybe (Matcher a))
-> Text
-> Maybe (Matcher a)
forall s a. s -> Getting a s a -> a
^. Getting
  (Text -> Maybe (Matcher a))
  (SearchFunctions a)
  (Text -> Maybe (Matcher a))
forall a. Lens' (SearchFunctions a) (Text -> Maybe (Matcher a))
makeMatcher) (Text -> Maybe (Matcher a)) -> Maybe Text -> Maybe (Matcher a)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe Text
t)
      where
        nc :: (Vector Int, (Int, Vector [Text]))
nc  = (Int -> Int -> Vector Int
forall a. (Unbox a, Num a) => a -> Int -> Vector a
U.enumFromN Int
0 (Vector Text -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector Text
v) , (Int
0 , Vector [Text] -> Vector [Text]
forall a. Vector a -> Vector a
force (Vector [Text] -> Vector [Text])
-> (Vector Text -> Vector [Text]) -> Vector Text -> Vector [Text]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Indices 0 -> [Text]) -> Vector (Indices 0) -> Vector [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\Indices 0
i -> [Vector Text
v Vector Text -> Int -> Text
forall a. Vector a -> Int -> a
! (Indices 0
i Indices 0 -> Getting Int (Indices 0) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (Indices 0) Int
forall s t a b. Field1 s t a b => Lens s t a b
_1)]) (Vector (Indices 0) -> Vector [Text])
-> (Vector Text -> Vector (Indices 0))
-> Vector Text
-> Vector [Text]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Vector (Indices 0) -> Vector (Indices 0)
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
convert (Vector (Indices 0) -> Vector (Indices 0))
-> (Vector Text -> Vector (Indices 0))
-> Vector Text
-> Vector (Indices 0)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int -> Vector (Indices 0)
emptyIndices (Int -> Vector (Indices 0))
-> (Vector Text -> Int) -> Vector Text -> Vector (Indices 0)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
512 (Int -> Int) -> (Vector Text -> Int) -> Vector Text -> Int
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Vector Text -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Vector Text -> Vector [Text]) -> Vector Text -> Vector [Text]
forall a b. (a -> b) -> a -> b
$ Vector Text
v))
        go :: Matcher a -> (Vector Int, (Int, Vector [Text]))
go (Matcher  MatcherSized n a
f') = (Vector Int
iv , (Vector Int -> Int
forall a. Unbox a => Vector a -> Int
U.length Vector Int
iv , Vector [Text] -> Vector [Text]
forall a. Vector a -> Vector a
force (Vector [Text] -> Vector [Text])
-> (Vector (Indices n) -> Vector [Text])
-> Vector (Indices n)
-> Vector [Text]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Indices n -> [Text]) -> Vector (Indices n) -> Vector [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\Indices n
i -> (SearchFunctions a
fs SearchFunctions a
-> Getting
     (MatcherSized n a -> Text -> Vector n Int -> [Text])
     (SearchFunctions a)
     (MatcherSized n a -> Text -> Vector n Int -> [Text])
-> MatcherSized n a
-> Text
-> Vector n Int
-> [Text]
forall s a. s -> Getting a s a -> a
^. Getting
  (MatcherSized n a -> Text -> Vector n Int -> [Text])
  (SearchFunctions a)
  (MatcherSized n a -> Text -> Vector n Int -> [Text])
forall a (n :: Nat).
KnownNat n =>
SimpleGetter
  (SearchFunctions a)
  (MatcherSized n a -> Text -> Vector n Int -> [Text])
displayer) MatcherSized n a
f' (Vector Text
v Vector Text -> Int -> Text
forall a. Vector a -> Int -> a
! (Indices n
i Indices n -> Getting Int (Indices n) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (Indices n) Int
forall s t a b. Field1 s t a b => Lens s t a b
_1)) (Indices n
i Indices n
-> Getting (Vector n Int) (Indices n) (Vector n Int)
-> Vector n Int
forall s a. s -> Getting a s a -> a
^. Getting (Vector n Int) (Indices n) (Vector n Int)
forall s t a b. Field2 s t a b => Lens s t a b
_2)) (Vector (Indices n) -> Vector [Text])
-> (Vector (Indices n) -> Vector (Indices n))
-> Vector (Indices n)
-> Vector [Text]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Vector (Indices n) -> Vector (Indices n)
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
convert (Vector (Indices n) -> Vector [Text])
-> Vector (Indices n) -> Vector [Text]
forall a b. (a -> b) -> a -> b
$ Vector (Indices n)
mv))
          where
            (Vector Int
iv , Vector (Indices n)
mv) = (SearchFunctions a
fs SearchFunctions a
-> Getting
     (MatcherSized n a
      -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
     (SearchFunctions a)
     (MatcherSized n a
      -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
-> MatcherSized n a
-> Vector Text
-> Vector Int
-> (Vector Int, Vector (Indices n))
forall s a. s -> Getting a s a -> a
^. Getting
  (MatcherSized n a
   -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
  (SearchFunctions a)
  (MatcherSized n a
   -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
forall a (n :: Nat).
KnownNat n =>
SimpleGetter
  (SearchFunctions a)
  (MatcherSized n a
   -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
lister) MatcherSized n a
f' Vector Text
v Vector Int
s

-- | Read a vector of newline separated candidates from the stdin.
readVectorStdIn :: IO (Vector Text)
readVectorStdIn :: IO (Vector Text)
readVectorStdIn  = IO (Vector Text) -> IO () -> IO (Vector Text)
forall a b. IO a -> IO b -> IO a
finally ((() -> IO (Maybe (Text, ()))) -> () -> IO (Vector Text)
forall (m :: * -> *) b a.
Monad m =>
(b -> m (Maybe (a, b))) -> b -> m (Vector a)
unfoldrM (IO (Maybe (Text, ())) -> () -> IO (Maybe (Text, ()))
forall a b. a -> b -> a
const (IO (Maybe (Text, ())) -> () -> IO (Maybe (Text, ())))
-> (IO Text -> IO (Maybe (Text, ())))
-> IO Text
-> ()
-> IO (Maybe (Text, ()))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO Bool
-> IO (Maybe (Text, ()))
-> IO (Maybe (Text, ()))
-> IO (Maybe (Text, ()))
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM IO Bool
isEOF (Maybe (Text, ()) -> IO (Maybe (Text, ()))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Text, ())
forall a. Maybe a
Nothing) (IO (Maybe (Text, ())) -> IO (Maybe (Text, ())))
-> (IO Text -> IO (Maybe (Text, ())))
-> IO Text
-> IO (Maybe (Text, ()))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Text -> Maybe (Text, ())) -> IO Text -> IO (Maybe (Text, ()))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\ !Text
l -> (Text, ()) -> Maybe (Text, ())
forall a. a -> Maybe a
Just (Text
l  , ())) (IO Text -> () -> IO (Maybe (Text, ())))
-> IO Text -> () -> IO (Maybe (Text, ()))
forall a b. (a -> b) -> a -> b
$ IO Text
T.getLine) ()) (Handle -> IO ()
hClose Handle
stdin)

-- | Read a vector of newline separated candidates from a handle.
readVectorHandle :: Handle -> IO (Vector Text)
readVectorHandle :: Handle -> IO (Vector Text)
readVectorHandle Handle
h = IO (Vector Text) -> IO () -> IO (Vector Text)
forall a b. IO a -> IO b -> IO a
finally ((() -> IO (Maybe (Text, ()))) -> () -> IO (Vector Text)
forall (m :: * -> *) b a.
Monad m =>
(b -> m (Maybe (a, b))) -> b -> m (Vector a)
unfoldrM (IO (Maybe (Text, ())) -> () -> IO (Maybe (Text, ()))
forall a b. a -> b -> a
const (IO (Maybe (Text, ())) -> () -> IO (Maybe (Text, ())))
-> (IO Text -> IO (Maybe (Text, ())))
-> IO Text
-> ()
-> IO (Maybe (Text, ()))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO Bool
-> IO (Maybe (Text, ()))
-> IO (Maybe (Text, ()))
-> IO (Maybe (Text, ()))
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (Handle -> IO Bool
hIsEOF Handle
h) (Maybe (Text, ()) -> IO (Maybe (Text, ()))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Text, ())
forall a. Maybe a
Nothing) (IO (Maybe (Text, ())) -> IO (Maybe (Text, ())))
-> (IO Text -> IO (Maybe (Text, ())))
-> IO Text
-> IO (Maybe (Text, ()))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Text -> Maybe (Text, ())) -> IO Text -> IO (Maybe (Text, ()))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\ !Text
l -> (Text, ()) -> Maybe (Text, ())
forall a. a -> Maybe a
Just (Text
l  , ())) (IO Text -> () -> IO (Maybe (Text, ())))
-> IO Text -> () -> IO (Maybe (Text, ()))
forall a b. (a -> b) -> a -> b
$ Handle -> IO Text
T.hGetLine Handle
h) ()) (Handle -> IO ()
hClose Handle
h)

-- | A generalized version of readVectorHandle allowing for the transformation of candidates and the resulting vector. See fileNamesSorted for an example of use.
readVectorHandleWith :: (Text -> Text) -- ^ The function to transform the candidates.
  -> (Vector Text -> Vector Text) -- ^ The function to apply to the constructed vector before compacting.
  -> Handle -- ^ The handle to read from
  -> IO (Vector Text)
readVectorHandleWith :: (Text -> Text)
-> (Vector Text -> Vector Text) -> Handle -> IO (Vector Text)
readVectorHandleWith Text -> Text
f Vector Text -> Vector Text
t Handle
h = IO (Vector Text) -> IO () -> IO (Vector Text)
forall a b. IO a -> IO b -> IO a
finally (Vector Text -> Vector Text
t (Vector Text -> Vector Text)
-> IO (Vector Text) -> IO (Vector Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (() -> IO (Maybe (Text, ()))) -> () -> IO (Vector Text)
forall (m :: * -> *) b a.
Monad m =>
(b -> m (Maybe (a, b))) -> b -> m (Vector a)
unfoldrM (IO (Maybe (Text, ())) -> () -> IO (Maybe (Text, ()))
forall a b. a -> b -> a
const (IO (Maybe (Text, ())) -> () -> IO (Maybe (Text, ())))
-> (IO Text -> IO (Maybe (Text, ())))
-> IO Text
-> ()
-> IO (Maybe (Text, ()))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO Bool
-> IO (Maybe (Text, ()))
-> IO (Maybe (Text, ()))
-> IO (Maybe (Text, ()))
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (Handle -> IO Bool
hIsEOF Handle
h) (Maybe (Text, ()) -> IO (Maybe (Text, ()))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Text, ())
forall a. Maybe a
Nothing) (IO (Maybe (Text, ())) -> IO (Maybe (Text, ())))
-> (IO Text -> IO (Maybe (Text, ())))
-> IO Text
-> IO (Maybe (Text, ()))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Text -> Maybe (Text, ())) -> IO Text -> IO (Maybe (Text, ()))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\ !Text
l -> (Text, ()) -> Maybe (Text, ())
forall a. a -> Maybe a
Just (Text -> Text
f (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$! Text
l  , ())) (IO Text -> () -> IO (Maybe (Text, ())))
-> IO Text -> () -> IO (Maybe (Text, ()))
forall a b. (a -> b) -> a -> b
$ Handle -> IO Text
T.hGetLine Handle
h) ())
                                     (Handle -> IO ()
hClose Handle
h)

-- | Read a vector of filenames from the handle, get the basename by removing the path of the directory. Finally sort and deduplicate the resulting filenames.
--   Useful to get the list of executables from PATH for example.
fileNamesSorted :: Handle -> IO (Vector Text)
fileNamesSorted :: Handle -> IO (Vector Text)
fileNamesSorted = (Text -> Text)
-> (Vector Text -> Vector Text) -> Handle -> IO (Vector Text)
readVectorHandleWith ((Char -> Bool) -> Text -> Text
T.takeWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/')) (Vector Text -> Vector Text
forall a. Eq a => Vector a -> Vector a
uniq (Vector Text -> Vector Text)
-> (Vector Text -> Vector Text) -> Vector Text -> Vector Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (forall s. MVector s Text -> ST s ()) -> Vector Text -> Vector Text
forall a.
(forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
modify forall s. MVector s Text -> ST s ()
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e, Ord e) =>
v (PrimState m) e -> m ()
sort)

-- | Search functions suitable for fuzzy matching. The candidate @c@ will match the query @s@ if @c@ contains all the characters in @s@ in order. In general there
--   can be several ways of matching. This tries to find a match with the minimum number of parts. It does not find the minimum number of parts, if that requires
--   reducing the extent of the partial match during search. E.g. matching @"as"@ against @"talash"@ the split will be @["tal","as","h"]@ and not
--   @["t","a","la","s","h"]@. While matching @"talash best match testing hat"@ against @"tea"@ will not result in @["talash best match ","te","sting h","a","t"]@ since
--   @"te"@ occurs only after we have match all three letters and we can't know if we will find the @"a"@ without going through the string.
searchFunctionsFuzzy :: SearchFunctions MatchPart
searchFunctionsFuzzy :: SearchFunctions MatchPart
searchFunctionsFuzzy = (Text -> Maybe (Matcher MatchPart))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n MatchPart
    -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n MatchPart -> Text -> Vector n Int -> [Text])
-> SearchFunctions MatchPart
forall a.
(Text -> Maybe (Matcher a))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n a
    -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n a -> Text -> Vector n Int -> [Text])
-> SearchFunctions a
SearchFunctions (CaseSensitivity -> Text -> Maybe (Matcher MatchPart)
fuzzyMatcher CaseSensitivity
IgnoreCase) (SearchSettings (MatcherSized n MatchPart) n
-> MatcherSized n MatchPart
-> Vector Text
-> Vector Int
-> (Vector Int, Vector (Indices n))
forall a (n :: Nat).
KnownNat n =>
SearchSettings a n
-> a
-> Vector Text
-> Vector Int
-> (Vector Int, Vector (Indices n))
searchSome (Int -> SearchSettings (MatcherSized n MatchPart) n
forall (n :: Nat).
KnownNat n =>
Int -> SearchSettings (MatcherSized n MatchPart) n
fuzzySettings Int
512)) (\MatcherSized n MatchPart
m Text
t -> Either Int (Vector Int) -> Text -> Vector Int -> [Text]
parts (Vector n Int -> Vector Int
forall (n :: Nat) a. Vector n a -> Vector a
S.fromSized (Vector n Int -> Vector Int)
-> Either Int (Vector n Int) -> Either Int (Vector Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MatcherSized n MatchPart -> Either Int (Vector n Int)
forall (n :: Nat) a. MatcherSized n a -> Either Int (Vector n Int)
sizes MatcherSized n MatchPart
m) Text
t (Vector Int -> [Text])
-> (Vector n Int -> Vector Int) -> Vector n Int -> [Text]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Vector n Int -> Vector Int
forall (n :: Nat) a. Vector n a -> Vector a
S.fromSized)

-- | Search functions that match the words in i.e. space separated substring in any order. @"talash best"@ will match @"be as"@ with the split
--   @["tal","as","h","be","st"]@ but "talash best" will not match @"bet"@.
searchFunctionsOL :: SearchFunctions Int
searchFunctionsOL :: SearchFunctions Int
searchFunctionsOL = (Text -> Maybe (Matcher Int))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n Int
    -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n Int -> Text -> Vector n Int -> [Text])
-> SearchFunctions Int
forall a.
(Text -> Maybe (Matcher a))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n a
    -> Vector Text -> Vector Int -> (Vector Int, Vector (Indices n)))
-> (forall (n :: Nat).
    KnownNat n =>
    MatcherSized n a -> Text -> Vector n Int -> [Text])
-> SearchFunctions a
SearchFunctions (CaseSensitivity -> Text -> Maybe (Matcher Int)
orderlessMatcher CaseSensitivity
IgnoreCase) (SearchSettings (MatcherSized n Int) n
-> MatcherSized n Int
-> Vector Text
-> Vector Int
-> (Vector Int, Vector (Indices n))
forall a (n :: Nat).
KnownNat n =>
SearchSettings a n
-> a
-> Vector Text
-> Vector Int
-> (Vector Int, Vector (Indices n))
searchSome (Int -> SearchSettings (MatcherSized n Int) n
forall (n :: Nat).
KnownNat n =>
Int -> SearchSettings (MatcherSized n Int) n
orderlessSettings Int
512)) (\MatcherSized n Int
m Text
t -> Either Int (Vector Int) -> Text -> Vector Int -> [Text]
partsOrderless (Vector n Int -> Vector Int
forall (n :: Nat) a. Vector n a -> Vector a
S.fromSized (Vector n Int -> Vector Int)
-> Either Int (Vector n Int) -> Either Int (Vector Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MatcherSized n Int -> Either Int (Vector n Int)
forall (n :: Nat) a. MatcherSized n a -> Either Int (Vector n Int)
sizes MatcherSized n Int
m) Text
t (Vector Int -> [Text])
-> (Vector n Int -> Vector Int) -> Vector n Int -> [Text]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Vector n Int -> Vector Int
forall (n :: Nat) a. Vector n a -> Vector a
S.fromSized)

-- testSearch :: IO ()
-- testSearch = (\v -> traverse_ print . take 64 . snd . snd . searchWithMatcher searchFunctionsFuzzy v (Just "figrun") . U.enumFromN  0 . length $ v) . getCompact
--               =<< readVectorStdIn