haskell-notes

method1 :: a -> …

method2 :: a -> …

methodN :: a -> …

Экземпляры классов типов

Нам встретилась одна конструкция определения экземпляров классов типов:

instance Name Type where

method1 x1 xN = …

method2 x1 xM = …

methodN x1 xP = …

Типы, значения и классы типов

Каждое значение имеет тип. Значение v имеет тип T на Haskell:

v :: T

Функциональный тип обозначается стрелкой: a -> b

fun :: a -> b

Тип значения может иметь контекст, он говорит о том, что параметр должен принадлежать классу типов:

fun1 :: С a

=> a -> a

fun2 :: (C1 a, C2, , CN) => a -> a

Суперклассы

Также контекст может быть и у классов, запись

class A a => B a where

Означает, что класс B целиком содержится в A, и перед тем как объявлять экземпляр для класса B, необ-

ходимо определить экземпляр для класса A. При этом класс A называют суперклассом для B.

1.7 Двумерный синтаксис

Наверное вы обратили внимание на то, что в Haskell нет разделителей строк и дополнительных скобок,

которые бы указывали границы определения классов или функций. Компилятор Haskell ориентируется по

переносам строки и отступам.

Так если мы пишем в классе:

class Eq a where

(==) :: a -> a -> a

(/=) :: a -> a -> a

По отступам за первой строкой определения компилятор понимает, что класс содержит два метода. Если

бы мы написали:

class Eq a where

(==) :: a -> a -> a

(/=) :: a -> a -> a

22 | Глава 1: Основы

То смысл был бы совсем другим. Теперь мы определяем класс Eq с одним методом == и указываем тип

некоторого значения (/=). Основное правило такое: конструкции, расположенные на одном уровне, вырав-

ниваются с помощью отступов. Чем правее находится определение, тем глубже оно вложено в какую-нибудь

специальную конструкцию. Пока нам встретилось лишь несколько специальных конструкций, но дальше

появятся и другие. Часто отступы набираются с помощью табуляции. Это удобно. Но лучше пользоваться

пробелами или настроить ваш любимый текстовый редактор так, чтобы он автоматически заменял табуля-

цию на пробелы. Зачем это нужно? Дело в том, что в разных редакторах на табуляцию может быть назначено

разное количество пробелов, так код набранный с двухзначной табуляцией будет очень трудно прочитать

если открыть его в редакторе с четырьмя пробелами вместо табуляции. Поскольку очень часто табуляция

перемежается с пробелами и выравнивание может “поехать”. Поэтому признаком хорошего стиля в Haskell

считается полный отказ от табуляции.

1.8 Краткое содержание

Итак подведём итоги: у нас есть две операции для определения типов (сумма и произведение) и по одной

для значений (синонимы), классов типов и экземпляров. А также бесконечное множество их комбинаций, из

которых и состоит увлекательный мир Haskell. Конечно не только из них, есть нюансы, синтаксический сахар,

расширения языка. Об этом и многом другом мы узнаем из этой книги.

Интересно, что в Haskell, несмотря на обилие конструкций и библиотек, ты чувствуешь, что за ними стоит

нечто из мира науки, мира чистого знания. Ты не просто учишься пользоваться определёнными функциями

или классами, а узнаёшь что-то новое и красивое.

1.9 Упражнения

Потренируйтесь в описаниях в рамках системы типов. Вы определяете базовые понятия и способы их

комбинирования. У вас есть три операции:

• Сумма типов data T = A1 | A2. Перечисление альтернатив

• Произведение типов data T = S S1 S2. Этим мы говорим, что понятие состоит из нескольких.

• Взятие в список [T]. Обозначает множественное число, элементов типа T их может быть несколько.

Опишите что-либо: комнату, дорогу, город, человека, главу из книги, математическую теорию, всё что

угодно.

Ниже приведён пример для понятий из этой главы:

data Program = Programm ProgramType [Module]

data ProgramType = Executable | Library

data Module = Module [Definition]

data Definition = Definition DefinitionType Element

data DefinitionType = Export | Inner

data Element = ET Type | EV Value | EC Class | EI Instance

data Type

= Type String

data Value

= Value String

data Class

= Class String

data Instance = Instance String

После того как вы закончите с описанием, подумайте, какие производные связи могли бы вас заинтере-

совать. Какие функции вам бы хотелось определить в этом описании. Выпишите их типы без определений,

например так:

— Все объявления типов в модуле

getTypes :: Module -> [Type]

— Провести редукцию значения:

reduce :: Value -> Program -> Value

— Проверить типы:

Краткое содержание | 23

checkTypes :: Program -> Bool

— Заменить все определения в модуле на новые

setDefinitions

:: Module -> [Definition] -> Module

— Упорядочить определения по какому-лбо принципу

orderDefinitions :: [Definition] -> [Definition]

Подумайте: если у вас есть все эти функции, какие производные значения могли бы вам сказать что-

нибудь интересное.

24 | Глава 1: Основы

Глава 2

Первая программа

Я вот говорю-говорю, а вдруг я вас обманываю, и ничего этого нет. В этой главе мы перейдём к програм-

мированию и запустим нашу первую программу в Haskell. Будет много примеров, на которых мы закрепим

наши знания.

2.1 Интерпретатор

Для запуска кода мы будем пользоваться приложением GHC (Glorious Glasgow Haskell Compiler) наиболее

Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162