ция readFile заняла файл, за счёт чтения по кусочкам. Для решения этой проблемы необходимо воспользо-
ваться энергичной версией функции readFile, она будет читать файл целиком. Эта функция живёт в модуле
System.IO.Strict:
import qualified System.IO.Strict asStrictIO
inFile ::( String -> String) -> FilePath -> IO()
inFile fun file =writeFile file .fun =<< StrictIO.readFile file
Функция main осталась прежней. Теперь наша программа спокойно переворачивает текст файла.
Аргументы программы
Пока программы, которые мы создавали просили пользователя ввести данные вручную при выполнении
программы, они работали в интерактивном режиме, но чаще всего программы принимают какие-нибудь
начальные данные, установки или флаги. Читать начальные данные можно с помощью функций из модуля
System.Environment.
Узнать, что передаётся в программу можно функцией getArgs :: IO[ String]. Она возвращает список
строк. Это те строки, что мы написали за именем программы через пробел при вызове в терминале. Напишем
простую программу, которая распечатывает свои аргументы по порядку, в виде пронумерованного списка.
module Main where
import System.Environment
main =getArgs >>=mapM_ putStrLn .zipWith f [1 ..]
wheref n a =show n ++”: ” ++a
В локальной функции f мы присоединяем к строке номер через двоеточие. Функцией mapM_ мы пробегаем
по списку строк, отображая их с помощью функции putStrLn. Обратите внимание на краткость программы,
с помощью функции композиции мы легко составили функцию, которая приписывает к аргументам числа, а
затем выводит их на экран.
Скомпилируем программу в интерпретаторе и вызовем её.
*Main> :!ghc --make Args
[1 of1] Compiling Main
( Args.hs, Args.o )
Linking Args ...
*Main> :! ./Argshey hey hey 23 54 ”qwe qwe qwe” fin
1 :hey
2 :hey
3 :hey
4 :23
5 :54
6 :qwe qwe qwe
7 :fin
Если мы хотим, чтобы аргумент-строка содержал пробелы мы заключаем его в двойные кавычки.
С помощью функции getProgName можно узнать имя программы. Создадим программу, которая здоро-
вается при вызове. И отвечает в зависимости от настроения программы. Настроение задаётся аргументом
программы.
module Main where
import Control.Applicative
import System.Environment
main =putStrLn =<<reply <$>getProgName <*>getArgs
132 | Глава 8: IO
reply :: String ->[ String] -> String
reply name (x :_) =hi name ++ casex of
”happy”
->”What a lovely day. What’s up?”
”sad”
->”Ooohh. Have you got some news for me?”
”neutral”
->”How are you?”
reply name _
=reply name [”neutral”]
hi :: String -> String
hi name =”Hi! My name is ” ++name ++”.\n”
В функции reply мы составляем реплику программы. Она зависит от имени программы и поступающих
на вход аргументов. Посмотрим, что у нас получилось:
*Main> :!ghc --make HowAreYou.hs -o ninja
[1 of1] Compiling Main
( HowAreYou.hs, HowAreYou.o )
Linkingninja ...
*Main> :! ./ninja happy
Hi! Myname is ninja .
Whata lovely day . What’sup ?
*Main> :! ./ninja sad
Hi! Myname is ninja .
Ooohh. Haveyou got some news for me ?
Вызов других программ
Мы можем вызвать любую программу из нашей программы. Это делается с помощью функции system,
которая живёт в модуле System.
system :: String -> IO ExitCode
Она принимает строку и запускает её в терминале. Так же как мы делали это с помощью приставки :!в
интерпретаторе. Значение типа ExitCodeговорит о результате выполнения строки. Он может быть успешным,
тогда функция вернёт ExitSuccessи закончиться ошибкой, тогда мы сможем узнать код ошибки по значению
ExitFailure Int.
Случайные значения
Функции для создания случайных значений определены в модуле System.Random. Модуль System.Random
входит в библиотеку random. Если в вашей поставке ghc его не оказалось, вы можете установить его вручную
через интернет, набрав в командной строке cabal install random. Сначала давайте разберёмся как гене-
рируются случайные числа. Стандартные случайные числа очень похожи на те, что были у нас, когда мы
рассматривали примеры специальных функций. У нас есть генератор случайных чисел типа g и с помощью
Читать дальше