8000 GitHub - vasnake/fp_haskell-c1: Функциональное программирование на языке Haskell / Денис Москвин / stepik
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Функциональное программирование на языке Haskell / Денис Москвин / stepik

License

Notifications You must be signed in to change notification settings

vasnake/fp_haskell-c1

Repository files navigation

FP Haskell

Часть 1 / 2 Функциональное программирование на языке Haskell / Денис Москвин / stepik / https://stepik.org/course/Функциональное-программирование-на-языке-Haskell-75 / https://stepik.org/75

Часть 2 / 2

Хороший вводный курс. Кратко, по делу, с интересными задачками. Не все задачки одинаково полезны, но, в целом, ОК. К сожалению, лектор часто тратит время на подробное объяснение тривиальных вещей, при этом важные концепции ФП и Хаскель упоминаются мимоходом. Эффект от этого огорчительный: внимание притупляется пространным рассуждением о банальных вещах и как только ты начинаешь зевать, хоп, проскакивает важная мысль. Если успел заметить -- молодец, иди гугли, что это было. Если не успел -- увы, ничего нового не узнал.

Предлагаю: к каждому степу давать список ссылок на материалы для самостоятельного изучения по данной теме.

Курс обязателен к изучению для всех, кто хочет разобраться в функциональном программировании. Терминология, паттерны решения проблем - это мастхев и оно тут есть.

Certificate https://stepik.org/cert/2317467?lang=en

short notes

Нотация и как её читать

  • Отступы важны и увеличение отступа означает "продолжение блока с предыущей строки".
  • foo :: Bar означает "нечто foo типа Bar". Bar это тип объекта foo. Например: getListMap :: [(k,v)] означает "getListMap имеет тип список туплей (ака пар)".
  • a -> b это базовый стрелочный тип, функция (отображение) из a в b. А и б это типы, которые населены множеством значений.
  • \ x -> some-expressions это декларация лямбды, лямбда-выражение. Функция, принимающая х и что-то делающая.
  • foo bar это применение ф. foo к параметру bar. Имеет наивысший приоритет и левую ассоциативность.
  • Скобочки (some-expressions) используются для группировки, явного определения ассоциативности, как конструктор кортежей (в сочетании с запятой ,). Особый случай: группировка унарного минуса и числа: (-42), без скобок отрицательное число нельзя записать.
  • Квадратные скобки [x, y, z] означают список (конструктор списка).
  • Фигурные скобки { foo::Int, bar::Char } означают record syntax в определении конструктора данных, где пара foo::Bar означает "метка::Тип".
  • Оператор "не-равно" записывается как /= в отличие от привычного !=.
  • Обратная стрелочка <- используется в list comprehension, в монадических цепочках (do-нотация), как метафора для "получить из" или "присвоить".
  • data: ключевое слово, начало определения типа данных (конструктор типа = конструктор(ы) данных)
  • type: ключевое слово, начало определения синонима (алиаса) типа (конструктор типа = конструктор типа)
  • newtype: ключевое слово, начало определения эфемерного типа с одним конструктором и одним параметром конструктора
  • case ... of ...: позволяет использовать пат.мат. в правой части уравнений.
  • do ...: запись цепочки монадических вычислений (пайплайн стрелок Клейсли, связанных оператором монадыц bind)
  • let ... in ..., where: два способа абстрагировать вычисления внутри функции

Существует охулиард "операторов", например ., $, &, <$> и т.д. Это инфиксные двух-параметрические функции, обладающие ассоциативностью (левой или правой) и приоритетом (число от 0 до 9), применение которых можно записывать не только в инфиксном, но и в префиксном виде, e.g. (+) 40 2. Полезно смотреть информацию по операторам в repl, e.g. ghci> :info (/=).

В интерпретаторе можно выполнять многострочные блоки кода, это делается так (см. маркеры :{, :})

ghci> :{
ghci| foo :: (Num b) => a -> b
ghci| foo x = 42
ghci| :}

repl

A parameter is a variable in a function definition. It is a placeholder and hence does not have a concrete value. An argument is a value passed during function invocation.

In logic, mathematics, and computer science, arity is the number of arguments or operands ... In mathematics, arity may also be called rank.... In logic and philosophy, arity may also be called adicity and degree In linguistics, it is usually named valency

Почему типы данных SomeTuple = Pair(a, b) и Maybe = Nothing | Just a называются, соответственно, "product" и "sum"? Название вытекает из ответа на вопрос: как посчитать область значений, покрываемую парой? a * b, перемножить мощности. Для суммы, разумеется, сложить мощности.

Когда вы слышите "сборка списка", надо понимать, что список собирается добавлением головы к хвосту. Т.е. сборка - это выращиевание списка добавлением элементов справа-налево let xs = 1:(2:(3:[]))

Работа с бесконечными последовательностями опирается на ленивость (вычисления до WHNF) и концепцию редукции-через-подстановки

В Haskell процесс вычисления результата - это череда подстановок

WHNF: слабая заголовочная нормальная форма, weak head normal form. Вычисления форсируются до этой формы.

foldr, foldl: два вида сверток, правая и левая. Правая умеет работать с бесконечностью, левая может быть оптимизирована (TCO).

Комбинатор: функция без свободных переменных, в теле только аргументы и операции применения. См. лямбда-исчисление.

Typeclass: это одно-параметрическое описание интерфейса (API), выделяющего некий "класс" типов. Чтобы тип стал членом этого класса, должен быть реализован instance для этого типа, воплощающий данный интерфейс.

Тип: может быть пользовательский (data, newtype, ...) или встроенный. Любое выражение имеет тип. Тип выражения выводится компилятором. Слово type используется для создания алиаса существующего типа.

Наблюдение: в ФП часто достаточно видеть сигнатуру (тип) функции, чтобы понять ее смысл, семантику. К этому надо стремиться в своем коде.

Type, Kind, Class: терминология иерархии типизации. Есть некое выражение (42 * pi), у него есть тип, возможно, оно состоит из других выражений и функций, которые должны быть совместимы по типам. Применение фунции к выражению проверяется на корректность через типы (параметров функции, действительных аргументов). Есть конструкторы типов, по сути - функции над типами. Их корректность проверяется через "над-типы" - виды (kind). Над выражениями есть типы, над типами есть кайнды.

А есть "классы" - class, это, на самом деле, type-class, т.е. классы типов. По сути - интерфейсы с одним параметрам типа, определяющие API для некоторого множества типов. Чтобы тип мог войти в конкретное множество (тайпкласс), для этого типа должен быть определен instance, в котором реализованы все обязательные методы интерфейса (class minimal complete definition).

type-class в Scala: параметризованный интерфейс, один параметр типа. Интерфейс определяет алгебру для множества возможных аргументов этого параметра.

Наиболее важные типы и классы типов

  • List: тип данных

  • Maybe: тип данных

  • Either: тип данных

  • Monoid: type-class (нейтральный элемент и бинарная операция)

  • Kleisli arrow: функция a -> m b где тип m это враппер над b, нужен для поддержки не-чистоты и не-тотальности функции a -> b.

  • Functor: type-class с одним методом fmap :: (a -> b) -> f a -> f b: поднимает функцию в контекст, aka оператор "применения" <$>. Структура "контейнера" не меняется. Законы функтора: 1) fmap id = id; 2) fmap (f . g) = (fmap f) . (fmap g).

  • Monad: тайпкласс с двумя методами return :: a -> m a aka pure поднимает значение в монаду, позволяет любую стрелку сделать стрелкой Клейсли k. bind :: m a -> (a -> m b) -> m b aka >>= оператор монадического связывания вычислений, структура "контейнера" может меняться (вычисления с эффектами). Законы монад: 1) левая "единица" pure (return a) >>= k = k a; 2) правая "единица" pure m >>= return = m; 3) ассоциативность bind (m >>= k1) >>= k2 = m >>= (\ x -> k1 x >>= k2)

В стдлиб обычно используется соглашение:

  • runFoo для запуска вычислений в монаде (и значение и эффекты),
  • execFoo для получения эффектов от вычислений (значение игнорируется),
  • evalFoo для получения значения и игнорирования эффектов

Semigroup, Monoid, Group

  • полугруппа - это где есть ассоциативная бинарная операция
  • моноид - это полугруппа с единицей
  • группа - это моноид с обратными элементами
  • Не любой моноид - группа, но любая группа - уже моноид.

links

Часть 2 / 2 Функциональное программирование на языке Haskell (часть 2) / https://stepik.org/693

Все подряд

About

Функциональное программирование на языке Haskell / Денис Москвин / stepik

Topics

Resources

License

Stars

Watchers

Forks

0