Haskell: навстречу функциональному программированию

Haskell — это функциональный язык программирования, разработанный специально для обработки символьных вычислений и списков.  

Данная статья носит обучающий характер и предназначена для новичков, стремящихся понять основные положения Haskell. 

Что такое Haskell? 

Haskell — широко распространенный чистый функциональный язык. 

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

Но в Haskell действует иной принцип — здесь мы говорим, что делать. Кроме того, это ленивый язык, поэтому программа не выполняет код, если считает его необязательным.  

Программа на Haskell — это не что иное, как ряд выполняющихся функций. 

Haskell — строго типизированный язык. Это значит, что компилятор достаточно сообразителен, чтобы определить тип объявленной переменной. Следовательно, у нас нет необходимости явно указывать ее тип. 

Настройка среды Haskell 

Для настройки среды Haskell на компьютере Windows перейдите по этой ссылке на официальный веб-сайт и загрузите соответствующий установочный пакет. 

Если же необходимо настроить эту среду в системе MAC, воспользуйтесь следующей ссылкой для перехода на официальный сайт и загрузите установщик Mac.

Процесс настройки в Linux выглядит следующим образом: 

$ sudo apt-get install haskell-platform

Начало работы с Haskell 

Вы без особого труда начнете программировать на Haskell — достаточно лишь ввести следующую команду в терминал: 

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done.
Prelude>

Вот теперь можно писать код. 

Пример программы 

Это простой пример, демонстрирующий динамизм Haskell. Рассмотрим следующий код:

 Prelude> main = putStrLn «Hello Medium»

Его результат: 

Hello Medium

Основные операции 

Haskell — настолько смышленый язык, что распознает число как число. Поэтому вам не нужно извне указывать его тип, как это обычно принято в других языках программирования. 

Пример: 

Prelude> 4*4

Результат:  

Prelude> 16

Символы 

Наряду с числами, Haskell способен распознавать символы, поступающие в него при вводе данных. 

Для отображения типа переменной можно ввести следующую строку кода

Prelude> :t "a"

и получить вот такой результат: 

"a" :: [Char]

Строки 

Строка — это не что иное, как набор символов. Создадим следующую строку

Prelude> "Hello Medium"

и увидим: 

"Hello Medium"

Если нужно узнать тип этой строки, снова воспользуйтесь :t:

Prelude> :t "Hello Medium"

В результате: 

"Hello Medium" :: [Char]

Как уже ранее упоминалось, строка — это просто набор символов, поэтому она вернется в качестве типа данных Char.

Логические типы данных 

С логическими типами всё также просто и понятно, как и с другими данными. Следующий пример демонстрирует некоторые из них. 

Prelude> True && True

или

Prelude> True && False

Списки 

Подобно другим типам данных в Haskell, List также обладает не меньшей практической значимостью. Как следует из примера, [a,b,c] представляет собой список символов. Следовательно, List — это набор элементов одного и того же типа данных, разделенных запятыми. Создадим свой список:

Prelude> x = [1,2,3,4,5]

Результат: 

[1,2,3,4,5]

Метод Length

Списки имеют несколько методов. Допустим, у вас есть список x, длину которого необходимо определить. Следующий метод как раз для вас: 

Prelude> length x

Метод Reverse

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

Prelude> reverse x

Метод Add

Для добавления элемента в список можно использовать оператор ++:

Prelude> x ++ y

Этот код объединяет два списка: x и y. 

Метод Delete

Используйте drop для удаления одного элемента из списка: 

Prelude>`drop n xs

Кортеж 

Haskell предоставляет еще один способ объявления нескольких значений в одном типе данных. Речь идет о кортеже, который можно рассматривать как список. Однако между ними есть ряд технических отличий. 

Кортеж содержит фиксированное число элементов. Он относится к неизменяемым типам. Создается кортеж следующим образом: 

Prelude> (8,16,'b')

В итоге: 

(8,16,'b')

Это кортеж содержит три элемента: два числа и символ. 

Как и в случае со списками, у кортежей есть методы, например, для определения в нем первого или последнего элемента.  

Первый элемент 

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

Prelude> fst (16, 8)

Его результат: 

16

Методы Head and tail

Метод head также предназначен для извлечения первого элемента кортежа: 

Prelude> head (16, 8, 24, 32)

В итоге: 

16

Метод tail позволит вам извлечь не только последний или второй элемент кортежа, но и все его элементы за исключением первого:

Prelude> tail(16, 8, 24, 32)

и в результате: 

[8, 24, 32]

Условные инструкции 

Условные инструкции — это программная возможность, позволяющая применять условие в процессе работы кода. Программист может выполнить набор инструкций в зависимости от предварительно заданного условия.  

Haskell располагает такими условными инструкциями, как:  

  • инструкция if-else; 
  • вложенная инструкция if-else.

Инструкция if-else 

Синтаксис выражений if выглядит следующим образом: 

if <condition> then <true-value> else <false-value>

Функции 

Функции играют важную роль в Haskell, поскольку он является языком функционального программирования. Подобно другим языкам, в нем существует определение и объявление функций.  

Следующий небольшой пример с функцией add поможет нам подробно разобраться в сути этой концепции. 

add :: Integer -> Integer -> Integer   --function declaration 
add x y = x + y --function definition
main = do 
putStrLn "The addition of the two numbers is:"
print(add 2 5) --calling a function

Результат: 

The addition of the two numbers is:
7

Сопоставление с образцом 

Этот метод предполагает сопоставление с конкретным типом выражения и позволяет упростить код. 

Рассмотрим следующий блок кода: 

fact :: Int -> Int 
fact 0 = 1 
fact n = n * fact ( n - 1 )

main = do 
   putStrLn "The factorial of 4 is:" 
   print (fact 4)

В данном примере метод сопоставления с образцом использовался для вычисления факториала числа. 

Охранные выражения 

Принцип охранных выражений очень похож на сопоставление с образцом, но вот используются они для тестирования свойств выражений. В следующем примере кода в программу факториала были внесены изменения с учетом концепции охранных выражений: 

fact :: Integer -> Integer 
fact n | n == 0 = 1 
       | n /= 0 = n * fact (n-1) 

main = do 
   putStrLn "The factorial of 4 is:"  
   print (fact 4)

Рекурсия 

Рекурсия — это ситуация, при которой функция вызывает саму себя. Haskell не предоставляет возможность повторять цикл выражения более одного раза. 

Он предлагает вам разбить всю функциональность на несколько разных функций и реализовать ее, используя рекурсию. 

В данном примере для вычисления факториала 4 использовались оба метода: сопоставление с образцом и рекурсия. 

fact :: Int -> Int 
fact 0 = 1 
fact n = n * fact ( n - 1 ) 

main = do 
   putStrLn "The factorial of 4 is:" 
   print (fact 4)

Лямбда-выражения

Функция, не имеющая определения, получила название лямбда-функции. Она обозначается символом \.

main = do 
   putStrLn "The successor of 5 is:"  
   print ((\x -> x + 1) 5)

Модули 

Если у вас был опыт программирования на Java, то вы в курсе, что все классы объединяются в папки, так называемые пакеты. Подобно этому и Haskell можно рассматривать как набор модулей.

Например, предлагаю вашему вниманию модуль list: 

import Data.List

И сразу функциональности List попадают в ваше распоряжение.

Среди других модулей можно выделить следующие: 

  • модуль Char
  • модуль Map
  • модуль Set

Пользовательские модули 

Создадим модуль Custom и определим в нем несколько функций. 

module Custom ( 
   showEven, 
   showBoolean 
) where 

showEven:: Int-> Bool 
showEven x = do 

if x 'rem' 2 == 0 
   then True 
else False 
showBoolean :: Bool->Int 
showBoolean c = do 

if c == True 
   then 1 
else 0

А теперь импортируем его программу, выполнив следующее действие: 

import Custom 

main = do 
   print(showEven 4) 
   print(showBoolean True)

Полезные ресурсы: 

Заключение 

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

Полагаю, что овладение Haskell упростит вам изучение других функциональных языков программирования. 

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Bryan Dijkhuizen: An Introduction to Functional Programming in Haskell

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: