Изучай Haskell во имя добра! (Липовача) - страница 116

Но не надо отчаиваться, не всё ещё потеряно. Оказывается, в языке Haskell есть весьма умная система для работы с функциями с побочными эффектами, которая чётко разделяет чисто функциональную и «грязную» части нашей программы. «Грязная» часть выполняет всю грязную работу, например отвечает за взаимодействие с клавиатурой и экраном. Разделив «чистую» и «грязную»части, мы можем так же свободно рассуждать о чисто функциональной части нашей программы, получать все преимущества функциональной чистоты, а именно – ленивость, гибкость, модульность, и при этом эффективно взаимодействовать с внешним миром.

Привет, мир!

До сих пор для того, чтобы протестировать наши функции, мы загружали их в интерпретатор GHCi. Там же мы изучали функции из стандартной библиотеки. Но теперь, спустя семь глав, мы наконец-то собираемся написать первую программу на языке Haskell! Ура! И, конечно же, это будет старый добрый шедевр «Привет, мир».

Итак, для начинающих: наберите в вашем любимом текстовом редакторе строку

>main = putStrLn "Привет, мир"



Мы только что определили имя >main; в нём мы вызываем функцию >putStrLn с параметром >"Привет, мир". На первый взгляд, ничего необычного, но это не так: мы убедимся в этом через несколько минут. Сохраните файл как helloworld.hs.

Сейчас мы собираемся сделать то, чего ещё не пробовали делать. Мы собираемся скомпилировать нашу программу! Я даже разволновался!.. Откройте ваш терминал, перейдите в папку с сохранённым файлом helloworld.hs и выполните следующую команду:

>$ ghc helloworld

>[1 of 1] Compiling Main   ( helloworld.hs, helloworld.o )

>Linking helloworld …

О’кей! При некотором везении вы получите нечто похожее и теперь можете запустить свою программу, вызвав >./helloworld.

>$ ./helloworld

>Привет, мир

ПРИМЕЧАНИЕ. Если вы используете Windows, то вместо выполнения команды >./helloworld просто запустите файл helloworld.exe.

Ну вот и наша первая программа, которая печатает что-то на терминале! Банально до невероятности!

Давайте изучим более подробно, что же мы написали. Сначала посмотрим на тип функции >putStrLn:

>ghci> :t putStrLn

>putStrLn :: String -> IO ()

>ghci> :t putStrLn "Привет, мир"

>putStrLn "Привет, мир" :: IO ()

Тип >putStrLn можно прочесть таким образом: >putStrLn принимает строку и возвращает действие ввода-вывода (I/O action) с результирующим типом >() (это пустой кортеж). Действие ввода-вывода – это нечто вызывающее побочные эффекты при выполнении (обычно чтение входных данных или печать на экране); также действие может возвращать некоторые значения. Печать строки на экране не имеет какого-либо значимого результата, поэтому возвращается значение