talash-0.1.0.0: Line oriented fast enough text search
Safe HaskellNone
LanguageHaskell2010

Talash.Internal

Synopsis

Search

data SearchFunctions a Source #

Constructors

SearchFunctions 

Fields

searchFunctionsFuzzy :: SearchFunctions MatchPart Source #

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.

searchFunctionsOL :: SearchFunctions Int Source #

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".

searchWithMatcher Source #

Arguments

:: SearchFunctions a

The configuration to use to carry out the search.

-> Vector Text

The vector v of candidates.

-> Maybe Text

The query string

-> 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.

-> (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 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.

Help for reading vectors

readVectorStdIn :: IO (Vector Text) Source #

Read a vector of newline separated candidates from the stdin.

fileNamesSorted :: Handle -> IO (Vector Text) Source #

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.

readVectorHandle :: Handle -> IO (Vector Text) Source #

Read a vector of newline separated candidates from a handle.

readVectorHandleWith Source #

Arguments

:: (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) 

A generalized version of readVectorHandle allowing for the transformation of candidates and the resulting vector. See fileNamesSorted for an example of use.

Exports

data Handle #

Haskell defines operations to read and write characters from and to files, represented by values of type Handle. Each value of this type is a handle: a record used by the Haskell run-time system to manage I/O with file system objects. A handle has at least the following properties:

  • whether it manages input or output or both;
  • whether it is open, closed or semi-closed;
  • whether the object is seekable;
  • whether buffering is disabled, or enabled on a line or block basis;
  • a buffer (whose length may be zero).

Most handles will also have a current I/O position indicating where the next input or output operation will occur. A handle is readable if it manages only input or both input and output; likewise, it is writable if it manages only output or both input and output. A handle is open when first allocated. Once it is closed it can no longer be used for either input or output, though an implementation cannot re-use its storage while references remain to it. Handles are in the Show and Eq classes. The string produced by showing a handle is system dependent; it should include enough information to identify the handle for debugging. A handle is equal according to == only to itself; no attempt is made to compare the internal state of different handles for equality.

Instances

Instances details
Eq Handle

Since: base-4.1.0.0

Instance details

Defined in GHC.IO.Handle.Types

Methods

(==) :: Handle -> Handle -> Bool #

(/=) :: Handle -> Handle -> Bool #

Show Handle

Since: base-4.1.0.0

Instance details

Defined in GHC.IO.Handle.Types

isEOF :: IO Bool #

The computation isEOF is identical to hIsEOF, except that it works only on stdin.

hIsEOF :: Handle -> IO Bool #

For a readable handle hdl, hIsEOF hdl returns True if no further input can be taken from hdl or for a physical file, if the current I/O position is equal to the length of the file. Otherwise, it returns False.

NOTE: hIsEOF may block, because it has to attempt to read from the stream to determine whether there is any more data to be read.

hClose :: Handle -> IO () #

Computation hClose hdl makes handle hdl closed. Before the computation finishes, if hdl is writable its buffer is flushed as for hFlush. Performing hClose on a handle that has already been closed has no effect; doing so is not an error. All other operations on a closed handle will fail. If hClose fails for any reason, any further operations (apart from hClose) on the handle will still fail as if hdl had been successfully closed.

stdin :: Handle #

A handle managing input from the Haskell program's standard input channel.

finally #

Arguments

:: IO a

computation to run first

-> IO b

computation to run afterward (even if an exception was raised)

-> IO a 

A specialised variant of bracket with just a computation to run afterward.

bracket #

Arguments

:: IO a

computation to run first ("acquire resource")

-> (a -> IO b)

computation to run last ("release resource")

-> (a -> IO c)

computation to run in-between

-> IO c 

When you want to acquire a resource, do some work with it, and then release the resource, it is a good idea to use bracket, because bracket will install the necessary exception handler to release the resource in the event that an exception is raised during the computation. If an exception is raised, then bracket will re-raise the exception (after performing the release).

A common example is opening a file:

bracket
  (openFile "filename" ReadMode)
  (hClose)
  (\fileHandle -> do { ... })

The arguments to bracket are in this order so that we can partially apply it, e.g.:

withFile name mode = bracket (openFile name mode) hClose

catch #

Arguments

:: Exception e 
=> IO a

The computation to run

-> (e -> IO a)

Handler to invoke if an exception is raised

-> IO a 

This is the simplest of the exception-catching functions. It takes a single argument, runs it, and if an exception is raised the "handler" is executed, with the value of the exception passed as an argument. Otherwise, the result is returned as normal. For example:

  catch (readFile f)
        (\e -> do let err = show (e :: IOException)
                  hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err)
                  return "")

Note that we have to give a type signature to e, or the program will not typecheck as the type is ambiguous. While it is possible to catch exceptions of any type, see the section "Catching all exceptions" (in Control.Exception) for an explanation of the problems with doing so.

For catching exceptions in pure (non-IO) expressions, see the function evaluate.

Note that due to Haskell's unspecified evaluation order, an expression may throw one of several possible exceptions: consider the expression (error "urk") + (1 `div` 0). Does the expression throw ErrorCall "urk", or DivideByZero?

The answer is "it might throw either"; the choice is non-deterministic. If you are catching any type of exception then you might catch either. If you are calling catch with type IO Int -> (ArithException -> IO Int) -> IO Int then the handler may get run with DivideByZero as an argument, or an ErrorCall "urk" exception may be propogated further up. If you call it again, you might get a the opposite behaviour. This is ok, because catch is an IO computation.

(^.) :: s -> Getting a s a -> a infixl 8 #

(^.) applies a getter to a value; in other words, it gets a value out of a structure using a getter (which can be a lens, traversal, fold, etc.).

Getting 1st field of a tuple:

(^. _1) :: (a, b) -> a
(^. _1) = fst

When (^.) is used with a traversal, it combines all results using the Monoid instance for the resulting type. For instance, for lists it would be simple concatenation:

>>> ("str","ing") ^. each
"string"

The reason for this is that traversals use Applicative, and the Applicative instance for Const uses monoid concatenation to combine “effects” of Const.

A non-operator version of (^.) is called view, and it's a bit more general than (^.) (it works in MonadReader). If you need the general version, you can get it from microlens-mtl; otherwise there's view available in Lens.Micro.Extras.

(?~) :: ASetter s t a (Maybe b) -> b -> s -> t infixr 4 #

(?~) is a version of (.~) that wraps the value into Just before setting.

l ?~ b = l .~ Just b

It can be useful in combination with at:

>>> Map.empty & at 3 ?~ x
fromList [(3,x)]

set :: ASetter s t a b -> b -> s -> t #

set is a synonym for (.~).

Setting the 1st component of a pair:

set _1 :: x -> (a, b) -> (x, b)
set _1 = \x t -> (x, snd t)

Using it to rewrite (<$):

set mapped :: Functor f => a -> f b -> f a
set mapped = (<$)

(.~) :: ASetter s t a b -> b -> s -> t infixr 4 #

(.~) assigns a value to the target. It's the same thing as using (%~) with const:

l .~ x = l %~ const x

See set if you want a non-operator synonym.

Here it is used to change 2 fields of a 3-tuple:

>>> (0,0,0) & _1 .~ 1 & _3 .~ 3
(1,0,3)

over :: ASetter s t a b -> (a -> b) -> s -> t #

over is a synonym for (%~).

Getting fmap in a roundabout way:

over mapped :: Functor f => (a -> b) -> f a -> f b
over mapped = fmap

Applying a function to both components of a pair:

over both :: (a -> b) -> (a, a) -> (b, b)
over both = \f t -> (f (fst t), f (snd t))

Using over _2 as a replacement for second:

>>> over _2 show (10,20)
(10,"20")

(%~) :: ASetter s t a b -> (a -> b) -> s -> t infixr 4 #

(%~) applies a function to the target; an alternative explanation is that it is an inverse of sets, which turns a setter into an ordinary function. mapped %~ reverse is the same thing as fmap reverse.

See over if you want a non-operator synonym.

Negating the 1st element of a pair:

>>> (1,2) & _1 %~ negate
(-1,2)

Turning all Lefts in a list to upper case:

>>> (mapped._Left.mapped %~ toUpper) [Left "foo", Right "bar"]
[Left "FOO",Right "bar"]

_1 :: Field1 s t a b => Lens s t a b #

Gives access to the 1st field of a tuple (up to 5-tuples).

Getting the 1st component:

>>> (1,2,3,4,5) ^. _1
1

Setting the 1st component:

>>> (1,2,3) & _1 .~ 10
(10,2,3)

Note that this lens is lazy, and can set fields even of undefined:

>>> set _1 10 undefined :: (Int, Int)
(10,*** Exception: Prelude.undefined

This is done to avoid violating a lens law stating that you can get back what you put:

>>> view _1 . set _1 10 $ (undefined :: (Int, Int))
10

The implementation (for 2-tuples) is:

_1 f t = (,) <$> f    (fst t)
             <*> pure (snd t)

or, alternatively,

_1 f ~(a,b) = (\a' -> (a',b)) <$> f a

(where ~ means a lazy pattern).

_2, _3, _4, and _5 are also available (see below).

_2 :: Field2 s t a b => Lens s t a b #

_3 :: Field3 s t a b => Lens s t a b #

type ASetter' s a = ASetter s s a a #

This is a type alias for monomorphic setters which don't change the type of the container (or of the value inside). It's useful more often than the same type in lens, because we can't provide real setters and so it does the job of both ASetter' and Setter'.

makeLenses :: Name -> DecsQ #

Generate lenses for a data type or a newtype.

To use it, you have to enable Template Haskell first:

{-# LANGUAGE TemplateHaskell #-}

Then, after declaring the datatype (let's say Foo), add makeLenses ''Foo on a separate line (if you do it before the type is declared, you'll get a “not in scope” error – see the section at the top of this page):

data Foo = Foo {
  _x :: Int,
  _y :: Bool }

makeLenses ''Foo

This would generate the following lenses, which can be used to access the fields of Foo:

x :: Lens' Foo Int
x f foo = (\x' -> foo {_x = x'}) <$> f (_x foo)

y :: Lens' Foo Bool
y f foo = (\y' -> foo {_y = y'}) <$> f (_y foo)

(If you don't want a lens to be generated for some field, don't prefix it with “_”.)

If you want to create lenses for many types, you can do it all in one place like this (of course, instead you just can use makeLenses several times if you feel it would be more readable):

data Foo = ...
data Bar = ...
data Quux = ...

concat <$> mapM makeLenses [''Foo, ''Bar, ''Quux]

When the data type has type parameters, it's possible for a lens to do a polymorphic update – i.e. change the type of the thing along with changing the type of the field. For instance, with this type

data Foo a = Foo {
  _x :: a,
  _y :: Bool }

the following lenses would be generated:

x :: Lens (Foo a) (Foo b) a b
y :: Lens' (Foo a) Bool

However, when there are several fields using the same type parameter, type-changing updates are no longer possible:

data Foo a = Foo {
  _x :: a,
  _y :: a }

generates

x :: Lens' (Foo a) a
y :: Lens' (Foo a) a

Finally, when the type has several constructors, some of fields may not be always present – for those, a Traversal is generated instead. For instance, in this example y can be present or absent:

data FooBar
  = Foo { _x :: Int, _y :: Bool }
  | Bar { _x :: Int }

and the following accessors would be generated:

x :: Lens' FooBar Int
y :: Traversal' FooBar Bool

So, to get _y, you'd have to either use (^?) if you're not sure it's there, or (^?!) if you're absolutely sure (and if you're wrong, you'll get an exception). Setting and updating _y can be done as usual.