{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} -- | An implementation of 'Language.Distance.Search' based on a BK-tree: -- . It performs reasonably, and it -- scales decently as the query distance increases. Moreover the data -- structure can work on any instance of 'EditDistance', or in fact any metric -- space - a generic interface is provided in 'Data.BKTree'. -- -- However, for very short distances (less than 3), -- 'Language.Distance.Search.TST' is faster. module Language.Distance.Search.BK ( -- * Data type BKTree -- * Operations , empty , insert , query , levenshtein , damerauLevenshtein ) where import Control.Arrow (second) import Data.ListLike (ListLike) import qualified Data.BKTree as BKTree import Language.Distance (EditDistance (..), Levenshtein, DamerauLevenshtein) import Language.Distance.Internal newtype BKTree full algo = BKTree (BKTree.BKTree full) empty :: forall full sym algo. (EditDistance sym algo, ListLike full sym) => BKTree full algo empty = BKTree (BKTree.empty (\s s' -> getDistance (distance s s' :: Distance algo))) insert :: (EditDistance sym algo, ListLike full sym) => full -> BKTree full algo -> BKTree full algo insert s (BKTree bk) = BKTree (BKTree.insert s bk) query :: (ListLike full sym, EditDistance sym algo) => Int -> full -> BKTree full algo -> [(full, Distance algo)] query maxd s (BKTree bk) = map (second Distance) $ BKTree.query maxd s bk levenshtein :: (ListLike full sym, EditDistance sym Levenshtein) => Int -> full -> BKTree full Levenshtein -> [(full, Distance Levenshtein)] levenshtein = query damerauLevenshtein :: (ListLike full sym, EditDistance sym DamerauLevenshtein) => Int -> full -> BKTree full DamerauLevenshtein -> [(full, Distance DamerauLevenshtein)] damerauLevenshtein = query