Haskell, Как создать упорядоченные данные Set a = Set [a]

Мне нужно создать "набор данных" Haskell

data Set a = Set [a]

Упражнение давайте реализуем простой тип данных Set. Набор — это список уникальные элементы. Набор всегда держится в порядке.

Implement the functions below. You might need to add class
constraints to the functions' types.

Examples:
member 'a' (Set ['a','b','c'])  ==>  True
add 2 (add 3 (add 1 emptySet))  ==>  Set [1,2,3]
add 1 (add 1 emptySet)  ==>  Set [1]

data Set a = Set [a]
deriving (Show,Eq)

до сих пор я определил:

-- emptySet is a set with no elements
emptySet :: Set a
emptySet = Set []

-- member tests if an element is in a set
member :: Eq a => a -> Set a -> Bool
member _ (Set[]) =  False
member a (Set (x:xs))  
    | (a == x) = True
    | otherwise = member a (Set xs)

но я изо всех сил пытаюсь определить метод «добавить», это не удается в тесте заказа

-- add a member to a set
add ::  Ord a => a -> Set a -> Set a
add a (Set[]) = Set[a] 
add a (Set (x:xs)) 
    | (a > x) && (not ( member a (Set (x:xs)) )) = add a (Set xs)
    | (a <= x) && (not ( member a (Set (x:xs)) )) = Set ( a :(x:xs) )     
    | (not ( member a (Set (x:xs)) )) = Set ((x:xs) ++ [a])
    | otherwise = Set (x:xs) 

Тесты не пройдены:

*** Failed! Falsified (after 6 tests):
add (Just 0) (Set [Nothing,Just (-5),Just 1,Just 3])
Expected: Set [Nothing,Just (-5),Just 0,Just 1,Just 3]
Was: Set [Just 0,Just 1,Just 3]

поэтому мой вопрос в том, как реализовать метод Add, но сохранить правильный порядок. или проще использовать вспомогательную функцию для упорядочения элементов после вставки.

Почему в Python есть оператор &quot;pass&quot;?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
1
0
819
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вам не нужен тест member на каждой итерации вашей функции add, потому что вы знаете, что Set отсортирован. Просто пройдитесь по списку, на каждом этапе сравнивая добавляемый элемент с передней частью набора. Если добавляемый элемент равен наименьшему элементу, то можно остановиться: элемент уже присутствует. Если он меньше наименьшего элемента, то вы нашли его точку вставки: если он меньше наименьшего элемента, он должен быть меньше всех элементов и, следовательно, должен быть добавлен. Наконец, если добавляемый элемент больше самого маленького элемента, просто продолжайте, пока не найдете его точку вставки.

Итак, следуя вашему ходу мыслей, я добавил :: Ord a => a -> Set a -> Set add a (Set[]) = Set[a] add a (Set (x:xs)) | (a == x) = Установить (x:xs) | (a < x) = Set ( a :(x:xs)) | в противном случае = Set([x]): (добавить (Set xs)) но показывает ошибку: Не удалось сопоставить ожидаемый тип [Set a]' with actual type Set a' | иначе = Set([x]): (добавить (Set xs)) ^^^^^^^^^^^^^^^

cealex 21.12.2020 12:16

@cealex Вы не можете : два Set, как в Set ([x] : .... Вы можете только : два списка. Итак, преобразуйте набор add a (Set xs) в список (как?), добавьте x, а затем преобразуйте окончательный список обратно в набор (как?).

chi 21.12.2020 13:35

@chi Не два списка, конечно. Скорее, один список и один элемент для добавления на передний план.

amalloy 21.12.2020 19:14

@amalloy Верно! Я упростил, так как OP начинался с двух наборов, первый из которых был синглтоном.

chi 21.12.2020 19:39

Ты пишешь

add a (Set (x:xs)) 
    | (a > x) && (not ( member a (Set (x:xs)) )) = add a (Set xs)
  --                                               ^^^^^^^^^^^^^^
....

add a (Set xs) это результат.

Где x? Разве он не должен присутствовать и в результате?

решение, которое я смог найти, основываясь на советах @amalloy и @chi, было

toLista :: Set a -> [a]
-- toLista (Set[]) = [] 
-- toLista (Set (x:xs)) = [x] ++ toLista ( Set (xs))

toLista (Set lista) = lista

add ::  Ord a => a -> Set a -> Set a
add a (Set[]) = Set[a] 
add a (Set (x:xs)) 
    | (a == x) = Set (x:xs)
    | (a < x) = Set ( a :(x:xs) )     
    | otherwise =  Set ( x : toLista ( add a (Set xs) ))

Существует гораздо более простой способ реализовать ваш toLista, не сопоставляя с шаблоном содержимое набора: toLista (set xs) = xs

amalloy 21.12.2020 23:09

Вы уже узнали о выражениях «как шаблоны» или case? Второй случай можно записать add a Set (xxs@(x:xs)) | a == x = Set xxs | a < x = Set (a : xxs) | otherwise = .... Я также предлагаю написать «списочную» версию, addList :: Ord a => a -> [a] -> [a], а затем обернуть ее: add a (Set l) = Set (addList a l). Это избавляет вас от необходимости возиться с применением и удалением конструктора Set в вашей рекурсии.

dfeuer 22.12.2020 00:42

Другие вопросы по теме