Шаг 208.
Основы языка Haskell. Монада вычислений с побочными эффектами IO. Функции организации последовательностей функций ввода-вывода

    На этом шаге мы перечислим эти функции.

    Конструктор типа IO является экземпляром класса Monad.

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

    Другими словами, монада - это абстракция управления.

    1. Функция, передающая управление от функции ввода-вывода, представляющей собой первый аргумент данной функции, функции ввода-вывода, представляющей собой второй аргумент данной функции:

   (>>):: IO a -> IO b -> IO b

    Функция (>>) используется там, где результат первой операции не представляет интереса.

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

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

    Функция (>>=) передаёт "часть" своего первого параметра в качестве аргумента второго параметра.

    3. Функция определяет результат операции ввода-вывода:

   return:: a -> IO a


    Пример. Рассмотрим построение функции, удаляющей из строки, вводимой с клавиатуры, всех символов, не являющихся прописными латинскими буквами.

    Вначале построим "обычную" функцию:

   fun:: String -> String
   fun = filter isUpper

    Теперь построим функцию

   main:: IO String
и проведём анализ типов используемых функций:
         IO String      String -> IO String
             ↓                  ↓       
   main = getLine  >>= \s -> return (fun s)
                                      ↑   
                                String -> String

    В заключение приведем небольшой демонстрационный пример.

   -- Демонстрация работы с последовательными операциями
   -- ввода-вывода (>>=), (>>), return
   ----------------------------------------------------
   -- Функция, перезаписывающая из файла "input" в файл
   -- "output" только буквы латинского алфавита
   --------------------------------------------
   main1:: IO ()
   main1 = readFile "input" 
           >>= \s -> writeFile "output" (filter isAlpha s)
           >> putStr "Фильтрация завершилась успешно! \n"  
   -------------------------------------------------------
   -- Функция, удаляющая из заданной строки x все символы,
   -- не являющиеся прописными латинскими буквами.
   --   Анализ типов используемых функций важен:
   --
   --   getLine:: IO String;
   --   return :: String -> IO String
   --   fun    :: String -> String
   --   (>>=)  :: IO String -> (String -> IO String)
   --                       -> IO String
   -------------------------------------
   main2:: IO String
   main2 = getLine >>= \s -> return (fun s)
   ----------------------------------------    
   fun:: String -> String  
   fun = filter isUpper
   -----------------------------------------
   -- Префиксная форма записи операции (>>=)
   ---------------------------------------------
   main2' = (>>=) getLine (\s -> return (fun s))   
   -----------------------------------------------
   -- Демонстрация реализации простейшего сложения
   ----------------------------------------------------
   main3 = putStr "Введите первое число: "          >>=
           \_ -> readLn                             >>=
           \x -> putStr "Введите второе число: "    >>=
           \_ -> readLn                             >>=
           \y -> putStrLn $ "Сумма = " ++ show(x+y)  
Файл с примерами можно взять здесь.

    На следующем шаге мы рассмотрим аксиомы монад.




Предыдущий шаг Содержание Следующий шаг