1632
правки
Изменения
м
* [[АВЛ-дерево]]: [http://pastebin.com/seB7yYyu ссылка на pastebin]
*: почему я не знал Haskell, когда это дерево было в лабе по дискретке на первом курсе? ;( просто списывается с конспекта один в один...
rollbackEdits.php mass rollback
=== Решение ===
В нормальной форме нет редукций. Если нормальная форма существует, то её можно достичь при помощи редукций [[#Нормальный порядок редукции|нормальным порядком]], а [[#Аппликативный порядок редукции|аппликативным ]] можно и не достичь.
# Уже в нормальное форме, как ни странно
== H1. Написать Haskell-код какой-нибудь структуру данных ==
* [[Квадродеревья | Квадродерево]]: [http://pastebin.com/jV4DeRvv ссылка на pastebin]
*: не совсем то, что требует Ян, но я пока не распарсил то, что он требует; возможно, более правильная версия появится позже
<font color=green>-- дано</font>
func = foldr (+) 0 . map (\x -> x * 10)
<font color=green>-- сначала перепишем композицию в обычную аппликацию для дальнейшей ясности</font>
func0 l = foldr (+) 0 (map (\x -> x * 10) l)
<font color=green>-- теперь инлайним foldr, то есть раскрываем его тело</font>
func1 l = '''case''' (map (\x -> x * 10) l) '''of'''
<font color=green>-- замечаем, что у нас получилось в конце выражение foldr (+) 0 (map (*10) ys), а это по сути наша функция func0,
которую мы раскрывали изначально, поэтому тому куску можно дать имя другое имя</font>
func5 l = '''case''' l '''of'''
[] -> 0
== zippers and functions differentiation ==
Для каждой структуры данных (datatype'а) в Haskell можно составить соответствующий ей zipper: это другая структура данных, которая позволяет "гулять" по нашей структуре, беря взяв в фокус текущий элемент, и запоминая при этом остальное состание состояние структуры данных (или контекст). Для списка легко придумывается zipper: мы находимся на какой-то позиции в списке, знаем значение элемента на этой позиции, знаем часть списка слева от текущего элемента и справа (для более глубокого понимания читай LearnYourHaskell). Поэтому zipper для листа списка имеет следующий вид:
<code>
</code>
Но не для всех типов получается легко придумать zipper методом пристального взгляда. Чтобы уметь составить zipper для произвольного типабез особых усилий, можно представить тип как функцию от параметра типа, а затем найти производную этого типа. Тогда если типу соответствует функция <tex> f(a) </tex>, то zipper выражается следующим образом: <tex> z(a) = a \cdot f'(a) </tex>.
Рассмотрим внимательней типа List:
<tex> f(a) = a^2 \cdot f(a) + f(a) + a^3 </tex>
Забудем на некоторое время, что мы работаем с типами. Продифференцируем обе части уравнение по переменной <tex> a </tex>, получим линейное уравнение относительно производной, а затем выразим её.
<tex> f'(a) = 2a \cdot f(a) + a^2 \cdot f'(a) + f'(a) + 3a^2 </tex>
Заметка: на этом надо остановиться и написать соответствующий рекурсивный тип. За дальнейшие действия будет сняты 0.5 баллов(ЯН: "слишком сложное решение")
<code>
<font color=green>-- Итого ответ:</font>
'''data''' DMice a = S a (Mice a) | H a (Mice a) | M a a (DMice a) | Y (DMice a) | A a a | K a a | Shmyak a a
</code>
Забавное, но бесполезное для сдачи ФП, продолжение:
Выразим производную.
<tex> f'(a) = \dfrac{2a \cdot f(a) + 3a^2}{1 - (a^2 + 1)} = (2a \cdot f(a) + 3a^2) \cdot \dfrac{1}{1 - (a^2 + 1)} \ (2)</tex>
В итоге у нас производная является произведением двух функций, а для типа это значит, что он является произведением двух типов. При умножении на константу у нас будет просто несколько одинаковых конструкторов с разными именами, поэтому распишем типа для первой скобки:.
<code>
<font color=green>--сначала распишем производную типа, полученного сразу после дифференцирования (1), если всё аккуратно раскрытьсоблюдать исходный порядок аргументов в типах</font>
'''data''' DMice a = S (Mice a) a | H a (DMice a) a | M a (Mice a) | Y (DMice a) | A a a | K a a | Shmyak a a
</code>