Metric spaces defined over strings; i.e. edit distance. > module Data.Metric.String ( > Hamming(..), > Levenshtein(..), > RestrictedDamerauLevenshtein(..) > ) where > > import Control.Applicative.Extras ((<$$>)) > import Data.Default (Default(def)) > import Data.Default.Instances.EditDistance () > import Data.Function (on) > import Data.List.Extras (count) > import Data.Metric.Class (Metric(..)) > import Data.Metric.Set (Discrete(..)) > import Text.EditDistance (levenshteinDistance, restrictedDamerauLevenshteinDistance) `Hamming` wraps Hamming distance: the number of positions between two *fixed length* strings at which the corresponding symbols are different. Equivalently, this can be seen as the minimum number of substitutions required to change one of the strings into the other. > newtype Hamming = Hamming > { getHamming :: String > } deriving (Eq, Show) > > instance Metric Hamming where > distance = count <$$> zipWith (distance `on` Discrete) `on` getHamming `Levenshtein` wraps Levenshtein distance: the minimum number of single-character operations-- insertions, deletions or substitutions-- required to make two strings equal. Here, we in effect re-export the heavily optimised implementation provided by Max Bolingbroke's excellent `edit-distance` package. > newtype Levenshtein = Levenshtein > { getLevenshtein :: String > } deriving (Eq, Show) > > instance Metric Levenshtein where > distance = fromIntegral <$$> levenshteinDistance def `on` getLevenshtein The Restricted-Damerau Levenshtein distance extends Levenshtein distance (above), with an additional operation: the transposition of two adjacent characters. It is 'restricted' in that the algorithm computes the minimum number of edit operations **under the condition that no substring is edited more than once.** Here, again, we're wrapping an implementation from `edit-distance`. > newtype RestrictedDamerauLevenshtein = RestrictedDamerauLevenshtein > { getRestrictedDamerauLevenshtein :: String > } deriving (Eq, Show) > > instance Metric RestrictedDamerauLevenshtein where > distance = fromIntegral <$$> restrictedDamerauLevenshteinDistance def `on` getRestrictedDamerauLevenshtein