monad transformers

Mar 05, 2010 14:31

Дисклеймер: это не туториал, это мысли для позднейшего обдумывания и, возможно, обсуждения.

Каждая монада вводит свой набор операций и способов их композиции. т.е. монада - это тройка

m:: * -> * (конструктор типа с одним парметром), return :: a -> m a , bind :: m a -> (a -> m b) -> m b
плюс некоторый набор операций, специфичных для монады.

монадический трансформер - это такая четвёрка
t :: ((* -> *) -> * -> *) , treturn a :: (Monad m) => a -> t m a, tbind ::(Monad m) => t m a -> (a -> t m b) -> t m b, lift :: (Monad m) => m a -> t m a

такое определение позволяет естественным образом поднимать простые операции из монады. Так, get:: m s && put s -> m () из понады state определяются в трансформере однозначно. А вот с менее тривиальными начинаются чудеса. В частности, посмотрим на функцию catchError :: (MonadError m e) => ( e -> m a) -> m a -> m a

Простого способа определить instance :: MonadError m e => MonadError (m t) e where catchError=smth - нет.

Вернее, есть простой, но неправильный - выразить операции над монадами с нетривиальными сигнатураси через специально определённый интерфейс с легко поднимаемыми сигнатурами. тогда оно должно завестись. Но это некрасиво и не факт, что сохранит нужные свойства.

В библиоткек mtl проблему разрешили в лоб, подняв соответствующие функции ручками. Однако более поздняя работа теоретическая работа нашла ошибки (todo: найти ссылку) и нарисовала правильные монадические трансформеры, расширив интерфейс трансформера (todo: разобраться, как у них это вышло. Одна дополнительная функция - это интересно).

Какие из этого могут быть плюшки? Ну, можно количество ручных лифтов в библиотеке трансформеров будет O(n) , а не O(n*n) и можно будет плодить трансформеры на каждый удобный случай.

funprog

Previous post Next post
Up