×
Traktatov.net » Изучай Haskell во имя добра! » Читать онлайн
Страница 17 из 245 Настройки
.

>ghci> let rightTriangles = [ (a,b,c) | c <– [1..10], b <– [1..c], a <– [1..b], a 2 + b 2 == c 2]

ПРИМЕЧАНИЕ. В консоли интерпретатора GHCi невозможно определять программные сущности в нескольких строках. Но в данной книге нам иногда приходится разбивать определения на несколько строк, чтобы код помещался на странице. В противном случае книга оказалась бы такой широкоформатной, что для неё вам пришлось бы купить гигантский книжный шкаф!

Почти закончили. Теперь давайте модифицируем функцию, чтобы получить треугольники, периметр которых равен 24.

>ghci> let rightTriangles' = [ (a,b,c) | c <– [1..10], b <– [1..c], a <– [1..b], a 2 + b 2 == c 2, a+b+c == 24]

>ghci> rightTriangles'

>[(6,8,10)]

Вот и ответ! Это общий шаблон в функциональном программировании. Вы берёте начальный набор решений и затем применяете преобразования и фильтруете их, пока не получите результат.

2

Типы и классы типов

Поверь в типы


Мы уже говорили о том, что Haskell является статически типизированным языком. Тип каждого выражения известен во время компиляции – это залог безопасного кода. Если вы напишете программу, которая попытается поделить булевский тип на число, то она даже не скомпилируется.

И хорошо, потому что уж лучше ловить такие ошибки на этапе компиляции, чем наблюдать, как ваша программа аварийно закрывается во время работы! Всему в языке Haskell назначен свой тип, так что компилятор может сделать довольно много выводов о программе перед её компиляцией.

В отличие от языков Java или Pascal, у Haskell есть механизм вывода типов. Если мы напишем число, то нет необходимости указывать, что это число. Язык Haskell может вывести это сам, так что нам не приходится явно обозначать типы функций и выражений.

Мы изучили некоторые основы языка, лишь вскользь упомянув о типах. Тем не менее понимание системы типов – очень важная часть обучения языку Haskell.

Тип – это нечто вроде ярлыка, который есть у каждого выражения. Он говорит нам, к какой категории относится данное выражение. Выражение >True – булево, >"привет" – это строка, и т. д.

Явное определение типов

А сейчас воспользуемся интерпретатором GHCi для определения типов нескольких выражений. Мы сделаем это с помощью команды >:t, которая, если за ней следует любое правильное выражение, выдаст нам тип последнего. Итак…

>ghci> :t 'a'

>'a' :: Char

>ghci> :t True

>True :: Bool

>ghci> :t "ПРИВЕТ!"

>"ПРИВЕТ!" :: [Char]

>ghci> :t (True, 'a')

>(True, 'a') :: (Bool, Char)

>ghci> :t 4 == 5

>4 == 5 :: Bool



Мы видим, что >:t печатает выражения, за которыми следуют >:: и их тип. Символы >:: означают: «имеет тип». У явно указанных типов первый символ всегда в верхнем регистре. Символ >'a', как вы заметили, имеет тип >Char. Несложно сообразить, что это сокращение от «character» – символ. Константа >True имеет тип >Bool. Выглядит логично… Идём дальше.

Исследуя тип >"ПРИВЕТ!", получим >[Char]. Квадратные скобки указывают на список – следовательно, перед нами «список символов». В отличие от списков, каждый кортеж любой длины имеет свой тип. Так выражение >(True, 'a') имеет тип >(Bool, Char), тогда как выражение