packages feed

fuzzyset-0.1.0.0: src/Data/FuzzySet/Util.hs

{-# LANGUAGE UnicodeSyntax #-}
module Data.FuzzySet.Util
  ( distance
  , enclosedIn
  , normalized
  , norm
  , substr
  , ε
  , (<$$>)
  , (−)
  , (×)
  ) where

import Data.Char                       ( isAlphaNum, isSpace )
import Data.HashMap.Strict             ( HashMap, empty )
import Data.Text                       ( Text, cons, snoc )
import Data.Text.Metrics
import Prelude.Unicode

import qualified Data.Text             as Text

-- | Normalize the input by
--
--     * removing non-word characters, except for spaces and commas; and
--     * converting alphabetic characters to lowercase.
normalized ∷ Text → Text
normalized = Text.filter word ∘ Text.toLower
  where
    word ch
      | isAlphaNum ch = True
      | isSpace    ch = True
      | (≡) ','    ch = True
      | otherwise     = False

-- | Return /n/ characters starting from offset /m/ in the input string.
substr ∷ Int  -- ^ Length of the substring
       → Int  -- ^ A character offset /m/
       → Text -- ^ The input string
       → Text -- ^ A substring of length /n/
{-# INLINE substr #-}
substr n m = Text.take n ∘ Text.drop m

-- | Insert the character /ch/ at the beginning and end of the input string.
enclosedIn ∷ Text → Char → Text
{-# INLINE enclosedIn #-}
enclosedIn str ch = ch `cons` str `snoc` ch

-- | Returns the euclidian norm, or /magnitude/, of the input list interpreted 
--   as a vector. That is, \( \sqrt{ \sum_{i=0}^n a_i^2 } \) for the input 
--   \( \langle a_0, a_1, \dots, a_n \rangle \) where \( a_i \) is the
--   element at position /i/ in the input list.
norm ∷ (Integral a, Floating b) ⇒ [a] → b
norm = sqrt ∘ fromIntegral ∘ sum ∘ fmap (^2)

-- | Return the normalized Levenshtein distance between the two strings.
distance ∷ Text → Text → Double
distance s t = fromRational (toRational d)
  where
    d = levenshteinNorm s t

-- | @(\<$$\>) = fmap ∘ fmap@
(<$$>) ∷ (Functor f, Functor g) ⇒ (a → b) → g (f a) → g (f b)
(<$$>) = fmap ∘ fmap
{-# INLINE (<$$>) #-}

-- | Empty HashMap
ε ∷ HashMap k v
ε = empty
{-# INLINE ε #-}

-- | Unicode minus sign symbol. Slightly longer than the hyphen-minus commonly
--   used, U+2212 aligns naturally with the horizontal bar of the + symbol.
(−) ∷ Num α ⇒ α → α → α
(−) = (-)
{-# INLINE (−) #-}

-- | Another unicode operator. This one for multiplication.
(×) ∷ Num α ⇒ α → α → α
(×) = (*)
{-# INLINE (×) #-}