Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[5]

£ то

Напишите функции parent и grandparent с сигнатурой (MonadPlus m) => Sheep -> m Sheep. Их удобно использовать в монадах списка и Maybe. Чем различается поведение функций при использовании их с монадой списка и монадой Maybe?

1.5. Поддержка монад в языке Haskell

Встроенные в Haskell средства поддержки монад определены в стандартном модуле Prelude, который экспортирует стандартные монадические функции, и в модуле Monad, который содержит реже используемые функции. Конкретные монадические типы содержатся в собственных библиотеках и описаны во второй части данного руководства.

1.5.1. В модуле Prelude

Модуль Prelude содержит описание класса Monad и нескольких вспомогательных функций для работы с монадическими типами данных.

1.5.1.1. Класс Monad

Мы уже встречались с определением класса Monad:

class Monad m where

(>>=)

(>>) return fail

m a -> (a -> m b) -> m b m a -> m b -> m b a -> m a

String -> m a

Минимальное описание: -- (>>=), return m >> k = m >>= \ -> k fail s = error s

1.5.1.2. Функции установления последовательности

Функция sequence берёт список монадических вычислений, по очереди активирует каждое из них и возвращает список результатов. Если какое-либо из вычислений завершается ошибкой, то и вся функция выдает ошибку:

sequence sequence

Monad m => [m a] -> m [a] foldr mcons (return [])

where mcons p q = p >>= \x -> q >>= \y -> return (x:y)

Функция sequence (обратите внимание на символ нижней черты) работает так же, как и sequence, но не возвращает список результатов. Она используется в случае, если важны только побочные эффекты монадических вычислений.

sequence sequence

Monad m => [m a] -> m ()

foldr (>>) (return ())

ФП 02005-03 01

Лист 21

Копипова Формат


1.5.1.3. Отображающие функции

Функция mapM применяет монадическое вычисление ко всем элементам списка и возвращает список результатов. Она определена с помощью функции map и функции sequence, описанной выше:

mapM f as

Monad m => (a -> m b) -> [a] -> m [b] sequence (map f as)

Для данной функции также существует версия с символом нижней черты, mapM , которая определяется с помощью функции sequence . Функция mapM работает так же, как и mapM, но не возвращает список результатов. Она используется в случае, если важны только побочные эффекты монадических вычислений.

mapM mapM f as

Monad m => (a -> m b) -> [a] -> m () sequence (map f as)

Являясь простым примером использования отображающих функций, функция putString для монады IO может быть определена следующим образом:

putString putString

[Char] -> IO () = mapM putChar s

Функция mapM может использоваться внутри блока do примерно так же, как функция map обычно используется со списками. Это распространенная ситуация - версия функции для использования внутри монады (т.е. рассчитанная на связывание) имеет сигнатуру, схожую с не монадической версией, но возвращаемые функцией значения находятся внутри монады:

- сравните монадическую и не монадическую сигнатуры map:: (a -> b) -> [a] -> [b]

mapM:: Monad m => (a -> m b) -> [a] -> m [b]

1.5.1.4. Функция обратного связывания (=<<)

В модуле Prelude также определена функция связывания, которая берёт аргументы в обратном порядке, нежели стандартная связывающая функция. Так как стандартная связывающая функция обозначается «>>=», обратная связывающая функция обозначается «=<<». Она полезна в случае, если связывающий оператор используется в качестве члена более высокого порядка и удобнее представить аргументы в обратном порядке. Её определение очень простое:

(=<<) :: Monad m => (a -> m b) -> m a -> m b f =<< x = x >>= f

ФП 02005-03 01

№ докум.

Копиоова Фоомат


£ то

1.5.2. В модуле Monad

Модуль Monad в стандартных библиотеках Haskell 98 экспортирует некоторые средства для более сложных монадических операций. Для использования этих средств нужно импортировать модуль Monad в вашу программу на языке Haskell.

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

1.5.2.1.Класс MonadPlus

В модуле Monad определен класс MonadPlus для монад с нулевым элементом и операцией «+»:

class Monad m => MonadPlus m where mzero:: m a

mplus:: m a -> m a -> m a

1.5.2.2.Монадические версии списковых функций

В модуле Monad определено несколько функций, обобщающих стандартные функции работы со списками на монады. Функции mapM экспортируются модулем Prelude и описаны выше.

Функция foldM - это монадическая версия функции foldl. Определение функции

foldM f a [] foldM f a (x:xs)

(Monad m) => (a -> b -> m a) -> a -> [b] -> m a return a

f a x >>= \y -> foldM f y xs

Однако проще понять принцип работы функции foldM, если рассмотреть её определение, записанное с помощью блока do:

-данный код не является допустимым в языке Haskell; -- это всего лишь иллюстрация.

foldM f a1 [x1, x2,xn] = doa2 <- f a1 x1

a3 <- f a2 x2

f an xn

Связывание справа налево достигается с помощью обращения входного списка перед вызовом функции foldM.

Мы можем воспользоваться функцией foldM при создании более мощной функции для составления запросов в нашем примере клонирования овец:

Код содержится в файле example3.hs

-traceFamily - общая функция для поиска родственников

traceFamily:: Sheep -> [ (Sheep -> Maybe Sheep) ] -> Maybe Sheep

ФП 02005-03 01

Лист 23

Копипова Формат



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25]