. Рассматривая эту аналогию с ящиками на ножках, вы можете понять, каким образом тип
>IO
действует как функтор.
Давайте посмотрим, как же это тип >IO
является экземпляром класса >Functor
… Когда мы используем функцию >fmap
для отображения действия ввода-вывода с помощью функции, мы хотим получить обратно действие ввода-вывода, которое делает то же самое, но к его результирующему значению применяется наша функция. Вот код:
>instance Functor IO where
> fmap f action = do
> result <– action
> return (f result)
Результатом отображения действия ввода-вывода с помощью чего-либо будет действие ввода-вывода, так что мы сразу же используем синтаксис >do
для склеивания двух действий и создания одного нового. В реализации для метода >fmap
мы создаём новое действие ввода-вывода, которое сначала выполняет первоначальное действие ввода-вывода, давая результату имя >result
. Затем мы выполняем >return (f result)
. Вспомните, что >return
– это функция, создающая действие ввода-вывода, которое ничего не делает, а только возвращает что-либо в качестве своего результата.
Действие, которое производит блок >do
, будет всегда возвращать результирующее значение своего последнего действия. Вот почему мы используем функцию >return
, чтобы создать действие ввода-вывода, которое в действительности ничего не делает, а просто возвращает применение >f result
в качестве результата нового действия ввода-вывода. Взгляните на этот кусок кода:
>main = do
> line <– getLine
> let line' = reverse line
> putStrLn $ "Вы сказали " ++ line' ++ " наоборот!"
> putStrLn $ "Да, вы точно сказали " ++ line' ++ " наоборот!"
У пользователя запрашивается строка, и мы отдаём её обратно пользователю, но в перевёрнутом виде. А вот как можно переписать это с использованием функции >fmap
:
>main = do
> line <– fmap reverse getLine
> putStrLn $ "Вы сказали " ++ line ++ " наоборот!"
> putStrLn $ "Да, вы точно сказали " ++ line ++ " наоборот!"
Так же как можно отобразить >Just "уфф"
с помощью отображения >fmap reverse
, получая >Just "ффу"
, мы можем отобразить и функцию >getLine
с помощью отображения >fmap
>reverse
. Функция >getLine
– это действие ввода-вывода, которое имеет тип >IO
>String
, и отображение его с помощью функции >reverse
даёт нам действие ввода-вывода, которое выйдет в реальный мир и получит строку, а затем применит функцию >reverse
к своему результату. Таким же образом, как мы можем применить функцию к тому, что находится внутри коробки >Maybe
, можно применить функцию и к тому, что находится внутри коробки >IO
, но она должна выйти в реальный мир, чтобы получить что-либо. Затем, когда мы привязываем результат к имени, используя запись