52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 137

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 137

readInit

:: IO Int

readConfig :: String -> IO Config

print

:: Show a => a -> IO ()

-- большая и сложная, но !чистая! функция

algorithm

:: Int -> Config -> Result

Функция readInit читает начальное значение, функция readConfig читает из файла наcтройки, функ-

ция print выводит значение на экран, если это значение можно преобразовать в строку. Функция algorithm

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

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

algorithm построена по правилам мира описаний. Так мы внесли порядок выполнения в программу, сохра-

нив возможность определения чистых функций.

Если у нас будет ещё один “кадр”, ещё одно действие, например как только функция algorithm закончила

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

вычисления с помощью какой-нибудь другой функции. Тогда наша программа примет вид:

program =

liftA2 algorithm2 readInit

(liftA2 algorithm1 readInit (readConfig ”file”))

>>= print

-- функции с побочными эффектами

readInit

:: IO Int

readConfig :: String -> IO Config

print

:: Show a => a -> IO ()

-- большие и сложные, но !чистые! функции

algorithm1

:: Int -> Config -> Result1

algorithm2

:: Int -> Result1 -> Result2

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

действия с пользователем. Но тип IO присутствует лишь в первых шести строчках, остальные два миллиона

строк написаны в мире описаний, исключительно чистыми функциями, которые поднимаются в мир специ-

альных функций с помощью функций liftA2 и стыкуются с помощью операции связывания >>=.

Попробуем тип IO в интерпретаторе. Мы будем пользоваться двумя стандартными функциями getChar и

print

-- читает символ с клавиатуры

getChar :: IO Char

-- выводит значение на экран

print :: IO ()

128 | Глава 8: IO

Функция print возвращает значение единичного типа, завёрнутое в тип IO, поскольку нас интересует не

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

Закодируем два примера из первого раздела. В первом мы читаем один символ и печатаем его дважды:

Prelude> :m Control.Applicative

Prelude Control.Applicative> let res = (\c -> c:c:[]) <$> getChar >>= print

Prelude Control.Applicative> res

q”qq”