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

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

:: (a’ -> b’) -> m’ a’ -> m’ b’

f

:: (a -> b -> c)

a

:: m a

lift1 f a

:: m (b -> c)

-- m’ == m, a’ == a, b’ == b -> c

Теперь в нашем определении для lift2 появится новое слагаемое g:

lift2 :: Kleisli m => (a -> b -> c) -> m a -> m b -> m c

lift2 f a b = ...

where g = lift1 f a

Один аргумент мы применили, осталось применить второй. Нам нужно составить выражение (g b), но

для этого нам нужна функция типа:

m (b -> c) -> m b -> m c

Эта функция применяет к специальному значению функцию, которая завёрнута в тип m. Посмотрим на

определение этой функции, мы назовём её $$:

($$) :: Kleisli m => m (a -> b) -> m a -> m b

mf $$ ma = ( +$ ma) *$ mf

Вы можете убедиться в том, что это определение проходит проверку типов. Посмотрим как эта функция

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

добавим в модуль Kleisli это определение и загрузим его в интерпретатор:

94 | Глава 6: Функторы и монады: теория

*Kleisli> :reload Kleisli

Ok, modules loaded: Kleisli, Nat.

*Kleisli> Just (+2) $$ Just 2

Just 4

*Kleisli> Nothing $$ Just 2

Nothing

*Kleisli> [(+1), (+2), (+3)] $$ [10,20,30]

[11,21,31,12,22,32,13,23,33]

*Kleisli> [(+1), (+2), (+3)] $$ []

[]

Обратите внимание на то, что в случае списков были составлены все возможные комбинации применений.

Мы применили первую функцию из списка ко всем аргументам, потом вторую функцию, третью и объединили

все результаты в список.

Теперь мы можем закончить наше определение для lift2:

lift2 :: Kleisli m => (a -> b -> c) -> m a -> m b -> m c

lift2 f a b = f’ $$ b

where f’ = lift1 f a

Мы можем записать это определение более кратко:

lift2 :: Kleisli m => (a -> b -> c) -> m a -> m b -> m c

lift2 f a b = lift1 f a $$ b

Теперь давайте добавим это определение в модуль Kleisli и посмотрим в интерпретаторе как работает

эта функция:

*Kleisli> :reload

[2 of 2] Compiling Kleisli

( Kleisli. hs, interpreted )

Ok, modules loaded: Kleisli, Nat.

*Kleisli> lift2 (+) (Just 2) (Just 2)