Ваша функция fromList
предполагает, что она получает несортированный список, который может содержать дубликаты, поэтому ей необходимо ограничение Ord
, чтобы выяснить, куда поместить элементы, и очистить дубликаты. Однако в этом случае вы получаете два списка, которые всегда будут отсортированы и не содержат дубликатов, и берете их декартово произведение, и результирующий список также будет отсортирован и не будет содержать дубликатов. Вместо того, чтобы использовать fromList
, чтобы превратить этот новый список в набор, вы должны создать для этой цели новую функцию, аналогично fromDistinctAscList
в реальном Set
. Чтобы построить это, разверните foldr insert Node
(я бы показал вам, как это сделать, но вы не опубликовали свою функцию insert
, поэтому я не могу), и замените все сравнения на жестко закодированный результат в зависимости от того, где они были , Тогда просто используйте его вместо fromList
. Это также даст выигрыш в производительности, поскольку избавляет от необходимости выполнять все избыточные сравнения.
Редактировать: ваша функция insert
совсем не заботится о поддержании какого-либо баланса двоичного дерева, поэтому вызов его в отсортированном списке приведет к максимально неуравновешенному дереву. Если вас это не волнует, то вот как вы можете реализовать fromDistinctAscList
:
insertLeast :: a -> Set a -> Set a
insertLeast x Leaf = singleton x
insertLeast x (Tree a left right) = Tree a (insertLeast x left) right
fromDistinctAscList :: [a] -> Set a -> Set a
fromDistinctAscList = foldr insertLeast Leaf
Они ведут себя точно так же, как insert
и fromList
, когда нет дубликатов и элементы находятся в в порядке возрастания Тем не менее, это имеет печальное следствие строгого foldr
, что плохо. Мы можем немного оптимизировать его следующим образом:
fromDistinctAscList :: [a] -> Set a -> Set a
fromDistinctAscList = foldr (`Tree` Leaf) Leaf
Это все равно будет максимально неуравновешенным, но теперь в другом направлении.
И вы также можете сделать свой обычный insert
Функция также ленивее:
insert :: Ord a => a -> Set a -> Set a
insert x xs = uncurry (Tree x) $ case xs of
Node -> (Node, Node)
Tree a left right -> case a `compare` x of
LT -> (insert a left, right)
EQ -> (left, right)
GT -> (left, insert a right)