ТОП 10:

Разделение «чистого» и «нечистого»



В этой главе вы узнаете, как вводить данные с клавиатуры и печа- тать их на экран. Начнём мы с основ ввода-вывода:

® Что такое действия?

® Как действия позволяют выполнять ввод-вывод?

® Когда фактически исполняются действия?

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

Мы уже упоминали, что Haskell – чисто функциональный язык. В то время как в императивных языках вы указываете компьютеру серию шагов для достижения некой цели, в функциональном про- граммировании мы описываем, чем является то или иное понятие. В языке Haskell функция не может изменить некоторое состояние, например поменять значение переменной (если функция изменяет состояние, мы говорим, что она имеет побочные эффекты). Единс- твенное, что могут сделать функции в языке Haskell, – это вернуть нам некоторый результат, основываясь на переданных им пара- метрах. Если вызвать функцию дважды с одинаковыми парамет- рами, она всегда вернёт одинаковый результат. Если вы знакомы с императивными языками, может показаться, что это ограничи- вает свободу наших действий, но мы видели, что на самом деле это даёт весьма мощные возможности. В императивном языке у вас нет


ПРИВЕТ, МИР! 205

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

Конечно, это хорошо, что фун- кции не могут изменять состояние: это помогает нам строить умозак- лючения о наших программах. Но есть одна проблема. Если функция

не может ничего изменить, как она сообщит нам о результатах вы- числений? Для того чтобы вывести результат, она должна изменить состояние устройства вывода – обычно это экран, который излуча- ет фотоны; они путешествуют к нашему мозгу и изменяют состоя- ние нашего сознания... вот так-то, чувак!

Но не надо отчаиваться, не всё ещё потеряно. Оказывается, в языке 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) с результи- рующим типом () (это пустой кортеж). Действие ввода-вывода – это нечто вызывающее побочные эффекты при выполнении (обычно чтение входных данных или печать на экране); также действие мо- жет возвращать некоторые значения. Печать строки на экране не имеет какого-либо значимого результата, поэтому возвращается зна- чение ().

ПРИМЕЧАНИЕ.Пустой кортеж имеет значение (), его тип – также ().

Когда будет выполнено действие ввода-вывода? Вот для чего нужна функция main. Операции ввода-вывода выполняются, если мы поместим их в функцию main и запустим нашу программу.

 







Последнее изменение этой страницы: 2017-02-17; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 35.170.78.142 (0.004 с.)