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

.

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

>import System.Random

>import Control.Monad(when)


>main = do

>  gen <- getStdGen

>  askForNumber gen


>askForNumber :: StdGen -> IO ()

>askForNumber gen = do

>   let (randNumber, newGen) = randomR (1,10) gen :: (Int, StdGen)

>   putStr "Я задумал число от 1 до 10. Какое? "

>   numberString <- getLine

>   when (not $ null numberString) $ do

>      let number = read numberString

>      if randNumber == number

>        then putStrLn "Правильно!"

>        else putStrLn $ "Извините, но правильный ответ "

>                                  ++ show randNumber

>            askForNumber newGen

Здесь мы создаём функцию >askForNumber, принимающую генератор случайных чисел и возвращающую действие ввода-вывода, которое спросит число у пользователя и сообщит ему, угадал ли он. В этой функции мы сначала генерируем случайное число и новый генератор, основываясь на исходном генераторе; случайное число мы называем >randNumber, а новый генератор – >newGen. Допустим, что было сгенерировано число 7. Затем мы предлагаем пользователю угадать, какое число мы задумали. Вызываем функцию >getLine и связываем её результат с идентификатором >numberString. Если пользователь введёт >7, >numberString будет равно >7. Далее мы используем функцию >when для того, чтобы проверить, не ввёл ли пользователь пустую строку. Если ввёл, выполняется пустое действие ввода-вывода >return(), которое закончит выполнение программы. Если пользователь ввёл не пустую строку, выполняется действие, состоящее из блока >do. Мы вызываем функцию >read со значением >numberString в качестве параметра, чтобы преобразовать его в число; образец >number становится равным >7.

ПРИМЕЧАНИЕ. На минуточку!.. Если пользователь введёт что-нибудь, чего функция >read не сможет прочесть (например, >"ха-ха"), наша программа «упадёт» с ужасным сообщением об ошибке. Если вы не хотите, чтобы программа «падала» на некорректном вводе, используйте функцию >reads: она возвращает пустой список, если у функции не получилось считать строку. Если чтение прошло удачно, функция вернёт список из одного элемента, содержащий пару, один компонент которой содержит желаемый элемент; второй компонент хранит остаток строки после считывания первого.

Мы проверяем, равняется ли >number случайно сгенерированному числу, и выдаём пользователю соответствующее сообщение. Затем рекурсивно вызываем нашу функцию >askForNumber, но на сей раз с вновь полученным генератором; это возвращает нам такое же действие ввода-вывода, как мы только что выполнили, но основанное на новом генераторе. Затем это действие выполняется.