Занятия с напарниками по Haskell (3)
Добрый вечер. Продолжаю делиться наблюдениями из нашей группы по изучению Haskell (
часть 1, часть 2 ). Скорее всего, пишу текст для себя, попутно повторяя \ вспоминая пройденный материал. Итак, поехали.
Прошли базовые функции для списков: head, tail, take, drop, !! . Отдельная благодарность автору книги в этом моменте, что он не стал подробно расписывать, какие же крутые это вещи, а просто обозначил их как API. Берите, пользуйтесь. Вы же не глупые: сможете различить, что значит взять голову списка, а что значит взять первые 5 элементов. Так что эту тему проскочили быстро.
А дальше начались базовые определения даже не столько языка Haskell, а программирования в целом. Type, scope, local bindings, data structure, list... Хорошо, что у каждого из нас есть какой-никакой программистский бэкграунд. Поэтому именно эти определения у нас не вызвали затруднения. А вот следующие термины уже нас напрягли.
Data declaration (0), type constructor (1), data constructor (2). Вот в наших головах слово "конструктор" связано с тем, что это функция, которая должна что-то создать. Конструктор может принимать аргументы. А когда мы пишем (0) data (1) Bool = (2) False | (2) True - тут вроде как ничего не создается в прошлом, привычном для нас понимании. Ну ок, допустим, что мы ввели новую сущность тип Bool. Да, он появился на свет, типа создался. Но False, True - почему их называем конструкторами? Это же значения, это данные, которые "населяют" наш Bool. Их не вызывают. Бесспорно , какие-то догадки есть. Кто-то наперед заглянул, кто-то гугл помучил. Но все равно очень непривычно. В этом моменте впервые столкнулись с тем, что наш предыдущий опыт скорее даже мешал, чем помогал в осознании текста книги.
Затем автор ввел понятие переменной типа (type variable). Заставил нас различать оператор ++ и функцию concat. Заставил прочувствовать разницу следующих сигнатур: 1) [a]->[a]->[a] и 2) [[a]] -> [a]. Признаюсь, вроде бы такой простой пример, но у меня с ним трудности. До сих пор спотыкаюсь на различии этих видов конкатенации. И там, и тут возвращаются списки. А как они получились - мне не важно. Может, как станет важно, так и все станет легко и прозрачно.
Дальше нас начали знакомить с базовыми типами. Научились отличать смысл следующих слов: Integral, Int, Integer. Через пару страниц посмеялись, что, оказывается, в комплект входят Int8, Int16... Все познается в сравнении. JS, твой универсальный double на все времена по сравнению с зоопарком в Haskell кажется таким простым. А Integer от Haskell удивительно похож по своей задумке на BigInt в JS. Вот интересно, а как можно считать бесконечно большие числа на компьютере, если не через биты памяти того же стандарта IEE-754? Переводить в строки, строить отдельный парсер... Кто знает, напиши в комментариях, в чем там фокус?
В итоге, мы научились чувствовать, что в Haskell есть отдельный уровень типизации, а есть отдельный уровень вычислений. Путать их нехорошо. Их надо держать под своим контролем в связке и согласованности. Еще попутно автор намекал, что нас ждут Type classes. Просил не расстраиваться. Сказал, что пока думайте о них как об интерфейсах в классических языках программирования про ООП. А потом, когда дойдем до этой темы, там все нам объяснит. Брр. Опять отсылка в будущее. Бесит.
А пока мы остановились на упражнениях по пройденному материалу: базовые операции над числами, строками, списками. Думается, что раз мы честно проходили материал и не позволяли халявить друг другу, то проблем с решением этих упражнений у нас не будет. Ну а если будут... - предлагайте ваши варианты =)
Лига программистов
2.1K поста11.9K подписчиков
Правила сообщества
- Будьте взаимовежливы, аргументируйте критику
- Приветствуются любые посты по тематике программирования
- Если ваш пост содержит ссылки на внешние ресурсы - он должен быть самодостаточным. Вариации на тему "далее читайте в моей телеге" будут удаляться из сообщества