Добрый день. Я опять возвращаюсь к вопросу, которой уже поднимал около 3х лет назад. Оптимизация поиска _наличия_ общего элемента 2х списков. Это опять оказалось слабым местом в производительности моей программы.
let original eq l =
l
|> List.fold
(fun acc el ->
if (acc |> List.exists (fun elLater -> eq el elLater))
then acc else el :: acc)
[]
|> List.rev
Да, тогда мне насоветовали использовать хэш таблицы и я сильно удивился, открыв код и увидев реализацию в лоб. Я переписал код:
let original (eq : 'a -> 'a -> bool when 'a : equality) l =
let hs = new HashSet<'a>(l, Comparer<'a>(eq))
hs.ToList().AsEnumerable() |> Seq.toList
Производительность разумеется выросла, но программа стала работать неправильно. Учитывая, что я поменял только код этой функции, я написал на неё несколько тестов и они все отработали верно, но программа целиком работала не правильно. Причина этого кроется в реализации Comparer:
type Comparer<'a>(f) =
interface System.Collections.Generic.IEqualityComparer<'a> with
member x.Equals(a, b) =
f a b
member x.GetHashCode(a) = hash(a.ToString())