haskell-notes

из Prelude:

module Logic where

import Prelude(Bool(.. ), Show(.. ), Eq(.. ))

Две точки в скобках означают “все конструкторы” (в случае типа) и “все методы” (в случае класса типа).

Строчку

import Prelude(Bool(.. ), Show(.. ), Eq(.. ))

Следует читать так: Импортируй из модуля Prelude тип Bool и все его конструкторы и классы Show и

Eq со всеми их методами. Если бы мы захотели импортировать только конструктор True, мы бы написали

Bool(True), а если бы мы захотели импортировать лишь имя типа, мы бы написали просто Bool без скобок.

Сначала выпишем в модуль наши синонимы:

module Logic where

import Prelude(Bool(.. ), Show(.. ), Eq(.. ))

true :: Bool

true = True

false :: Bool

false = False

not :: Bool -> Bool

not True

= False

not False = True

and :: Bool -> Bool -> Bool

and False

_

= False

and True

x

= x

or

:: Bool -> Bool -> Bool

or True

_ = True

or False

x = x

xor :: Bool -> Bool -> Bool

xor a b = or (and (not a) b) (and a (not b))

ifThenElse :: Bool -> a -> a -> a

ifThenElse True

t

_ = t

ifThenElse False

_

e = e

Теперь сохраним модуль и загрузим его в интерпретатор. Для наглядности мы установим флаг +t, при

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

*Logic> :l Logic

[1 of 1] Compiling Logic

( Logic. hs, interpreted )

Ok, modules loaded: Logic.

*Logic> :set +t

*Logic> not (and true False)

True

it :: Bool

*Logic> or (and true true) (or False False)

True

it :: Bool

*Logic> xor (not True) (False)

False

it :: Bool

*Logic> ifThenElse (or true false) True False

True

it :: Bool

Логические значения | 27

Разумеется в Haskell уже определены логические операции, здесь мы просто тренировались. Они называ-

ются not, (&& ), ||. Операция xor это то же самое, что и (/=). Для Bool определён экземпляр класса Eq. Также

в Haskell есть конструкция ветвления она пишется так:

x = if cond then t else e

Слова if, then и else – ключевые. cond имеет тип Bool, а t и e одинаковый тип.

В коде программы обычно пишут так:

x = if a > 3

then ”Hello”

else (if a < 0

then ”Hello”

else ”Bye”)

Отступы обязательны.

Давайте загрузим в интерпретатор модуль Prelude и наберём те же выражения стандартными функция-

ми:

*Logic> :m Prelude

Prelude> not (True && False)

True

it :: Bool

Prelude> (True && True) || (False || False)

True

it :: Bool

Prelude> not True /= False

False

it :: Bool

Prelude> if (True || False) then True else False

True

it :: Bool

Бинарные операции с символьными именами пишутся в инфиксной форме, то есть между аргументами

как в a && b или a + b. Значение с буквенным именем также можно писать в инфиксной форме, для этого

оно заключается в апострофы, например a ‘and‘ b или a ‘plus‘ b. Апострофы обычно находятся на одной

кнопке с буквой “ё”. Также символьные функции можно применять в префиксной форме, заключив их в

скобки, например (&& ) a b и (+) a b. Попробуем в интерпретаторе:

Prelude> True && False

False

it :: Integer

Prelude> (&& ) True False

False

it :: Bool

Prelude> let and a b = a && b

and :: Bool -> Bool -> Bool

Prelude> and True False

False

it :: Bool

Prelude> True ‘and‘ False

False

it :: Bool

Обратите внимание на строчку let and a b = a && b. В ней мы определили синоним в интерпретаторе.

Сначала мы пишем ключевое слово let затем обычное определение синонима, как в программе. Это простое

однострочное определение, но мы можем набирать в интерпретаторе и более сложные. Мы можем написать

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

Prelude> let not2 True = False; not2 False = True

Мы можем записать это определение более наглядно, совсем как в редакторе, если воспользуемся много-

строчным вводом. Для этого просто наберите команду :{. Для выхода воспользуйтесь командой :}. Отметим,

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

определений и мы хотим записать их покомпактней, мы можем сделать это так:

a1 = 1;

a2 = 2;

a3 = 3

a4 = 4;

a5 = 5;

a6 = 6

28 | Глава 2: Первая программа

2.4 Класс Show. Строки и символы

Мы набираем в интерпретаторе какое-нибудь сложное выражение, или составной синоним, интерпрета-

тор проводит редукцию и выводит ответ на экран. Откуда интерпретатор знает как отображать значения

типа Bool? Внутри интерпретатора вызывается метод класса Show, который переводит значение в строку. И

затем мы видим на экране ответ.

Для типа Bool экземпляр класса Show уже определён, поэтому интерпретатор знает как его отображать.

Обратите внимание на эту особенность языка, вид значения определяется пользователем, в экземпляре

класса Show. Из соображений наглядности вид значения может сильно отличаться от его внутреннего пред-

ставления.

В этом разделе мы рассмотрим несколько примеров с классом Show, но перед этим мы поговорим о стро-

ках и символах в языке Haskell.

Строки и символы

Посмотрим в интерпретаторе на определение строк (тип String), для этого мы воспользуемся командой

:i (сокращение от :info):

Prelude> :i String

type String = [Char]

— Defined in ‘GHC.Base’

Интерпретатор показал определение типа и в комментариях указал в каком модуле тип определён. В

Страницы: 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