Задание выполняется на Scala в соответствии с изученным на лекции.
Тип данных натуральных чисел задан как
sealed trait Nat
case object Z
case class Succ(s: Nat)
Реализуйте для натуральных чисел следующие объекты:
Num[Nat]
- операции сложения, умножения и вычитанияEq[Nat]
- операция сравнения
Тип данных дерева состоит из двух частей:
- Лист дерева, не содержит данных
- Узел дерева. Содержит непустой список одинаковых значений и имеет двух детей.
Двоичное дерево называется двоичным деревом поиска если оно удовлетворяет следующему условию: значения всех элементов в левом поддереве меньше значения в узле, а значения элементов в правом поддереве больше значения в узле.
Рекомендуется использовать NonEmpty
.
Реализуйте следующие операции с двоичным деревом поиска:
- Проверка на пустоту
- Поиск заданного элемента в дереве (используйте тот факт, что дерево является деревом поиска)
- Вставка нового элемента в двоичное дерево поиска. Если вставляемый элемент уже находится в дереве, то необходимо добавить его в список того узла, в котором этот элемент находится. Тут следует обратить внимание, что если в узле дерева есть список элементов, то этот список всегда непустой.
- Удаление заданного элемента из дерева
- Конвертирование списка чисел в дерево
Реализуйте Foldable
для Tree
, таким образом, чтобы запись
foldable.toList(fromList(list)) == list.sorted
была верной. Для реализации разрешается использовать все методы списков и Foldable[NonEmpty]
.
Требуется реализовать foldr
и foldMap
руками (не используя в описании одного другой).
Реализуйте Functor
, Applicative
, Monad
для NonEmpty
. Для реализации разрешается использовать все методы списков.
Дан тип парсера строки
case class Parser[A](runParser: String => Option[(A, String)])
Функция runParser
запускается для входной строки и "поглощает" буквы, т.е. если парсер считывает (поглощает) одну
букву из строки "123"
, то его функция вернёт Some("1", "23")
. Парсер может "падать" на входе, возвращая при
это None
.
- Реализуйте для него
Functor
,Applicative
,Alternative
,Monad
- Реализуйте следующие парсеры-комбинаторы:
ok
- парсер никогда не падает, и не поглощает входeof
- проверяет, что парсер дошёл до конца строки, иначе падаетsatisfy
- принимает предикат на букву, и возвращает эту букву, убирая её из строки, если предикат на букве равенTrue
, иначе падает.element
иstream
- парсят одну или несколько букв
- Используя реализованные парсеры-комбинаторы (добавляя недостающее по необходимости) реализуйте парсеры для:
- Парсер строк-ab - строк, которые содержат только последовательные символы
ab
-abababab...
. Парсер должен падать, если строка не удовлетворяет условию. - Парсер целого числа, перед которым может быть знак
+
или-
- (Бонус 10) Парсер правильных скобочных последовательностей (падает, если последовательность неправильная, не падает, если правильная)
- Парсер строк-ab - строк, которые содержат только последовательные символы
При выполнении 3 пункта необходимо использовать абстракции из первой части задания.
Полезные ссылки и информация для 5:
- Parser Combinators: Basics
- Alternative - имеет единственный метод
orElse
, который позволяет соединить две коробки. Например, в случаеOption
, если одна из коробок пустая, вернётся вторая. SeeAlternativeExample
. С парсеромAlternative
работает так же - сначала пробует первый, потом, если не вышло - второй.