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


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




[7]

£ то

и результатом allCombinations (*) [[0, 1], [1, 2], [3, 5]] будет [0 * 1 * 3, 0 * 1 * 5, 0 * 2 * 3, 0 * 2 * 5, 1 * 1 * 3, 1 * 1 * 5, 1 * 2 * 3, 1 * 2 * 5], или [0, 0, 0, 0, 3, 5, 6, 10]

(a -> a -> a) -> [[a]] -> [a]

foldl (liftM2 fn) l ls

allCombinations:

allCombinations fn []=

allCombinations fn (l:ls) =

Существует функция ap, которую иногда удобнее использовать, нежели втягивающие функции. Функция представляет собой функциональный аппликативный оператор ($), втянутый в монаду:

ap :: (Monad m) => m (a -> b) -> m a -> m b

ap = liftM2 ($)

Обратите внимание, что liftM2f xy эквивалентно returnf aps x apsy, и так далее для функций с большим количеством аргументов. Функция ap удобна для работы с функциями более высоких порядков и монадами.

Результат работы функции ap зависит от алгоритма монады, в которой она используется. Поэтому, например, [( * 2), ( + 3)] apy [0, 1, 2] эквивалентно [0, 2, 4, 3, 4, 5] и (Just ( * 2)) aps (Just 3) эквивалентно Just 6. Вот простой пример того, насколько удобна функция ap при проведении вычислений более высоких порядков:

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

-- lookup the commands and fold ap into the command list to - compute a result.

main main

(2 * )), ( "div" 2)), (\x -> x * x)), negate),

let fns = [("double" ("halve", ("square" ("negate" ("incr", ( + 1)), ("decr", ( + (-1)))]

args <- getArgs

let val = read (args !! 0)

cmds = map ((flip lookup) fns) (words (args!!1)) print $ foldl (flip ap) (Just val) cmds

1.5.2.5. Функции, используемые с MonadPlus

В модуле Monad определены две функции, которые используются с монадами, имеющими нулевой элемент и операцию «+». Первая из них - это функция msum, аналогичная функции sum, определённой для списка чисел. Функция msum оперирует списками монадических значений и применяет оператор mplus к списку, используя mzero как начальное значение:

msum:: MonadPlus m => [m a] -> m a

ФП 02005-03 01

Лист 27

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


£ то

msum xs

foldr mplus mzero xs

В монаде списка функция msum эквивалентна функции concat. В монаде Maybe функция msum возвращает первое в списке значение, не равное Nothing. Аналогично, поведение функции msum в других монадах зависит от природы определений их нулевых элементов (mzero) и функций «+» (mplus).

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

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

type Variable=

type Value=

type EnvironmentStack =

String String

[[(Variable, Value)]]

- Функция lookupVar извлекает значение переменной из стека.

она использует функцию msum в монаде Maybe для получения

первого значения, не равного Nothing lookupVar:: Variable -> EnvironmentStack -> Maybe Value

lookupVar var stack= msum $ map (lookup var) stack

вместо этого:

lookupVar lookupVar var [] lookupVar var (e:es)

Variable -> EnvironmentStack -> Maybe Value Nothing

let val = lookup var e in maybe (lookupVar var es) Just val

Вторая функция, используемая с монадами, имеющими нулевой элемент и функцию «+», это guard:

guard :: MonadPlus m => Bool -> m () guard p = if p then return () else mzero

Ключ к пониманию этой функции заключается в законе монад с нулевым элементом и функцией «+», который гласит: mzero >>=f = = mzero. При включении функции guard в последовательность монадических операций любое вычисление, охранное выражение в котором принимает значение False, возвращает mzero. Это аналогично тому, как в случае работы со списками действует охранное выражение l = = [].

Следующий пример демонстрирует использование функции guard в монаде Maybe:

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

data Record type DB

Rec {name :: String, age :: Int} deriving Show [Record]

Функция getYoungerThan возвращает все записи о людях младше определенного возраста.

она использует функцию guard для исключения записей о людях,

ФП 02005-03 01

Лист 28

№ йокум.

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


-возраст которых равен или больше заданного предела. Этот пример создан чисто в демонстрационных целях.

-В реальной жизни было бы проще

воспользоваться фильтром. Функция guard становится полезнее, если -- критерии отбора более сложные.

getYoungerThan:: Int -> DB -> [Record]

getYoungerThan limit db= mapMaybe (\r ->

guard (age r < limit) return r)

1.5.3. Резюме

Стандартные библиотеки языка Haskell содержат некоторые функции для работы с монадами. Класс Monad и наиболее часто используемые функции определены в модуле Prelude. Класс MonadPlus и реже используемые (но вс же очень полезные!) функции определены в модуле Monad. Множество других типов в библиотеках языка Haskell объявлены в соответствующих модулях экземплярами классов Monad и MonadPlus.

ФП 02005-03 01

Лист 29

№ докум.

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



[стр.Начало] [стр.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]