В настоящее время я испытываю трудности с трансформаторами монады. Я определяю несколько разных недетерминированных отношений, которые используют трансформаторы. К сожалению, у меня возникли проблемы с пониманием того, как правильно переводить из одной эффективной модели в другую.Трансформация под трансформаторами
Предположим, что эти отношения являются «foo» и «bar». Предположим, что «foo» связывает As и Bs с Cs; предположим, что «бар» связывает Bs и Cs с Ds. Мы определим «бар» в терминах «foo». Чтобы сделать интереснее, вычисление этих отношений потерпит неудачу по-разному. (Поскольку бар соотношение зависит от Foo отношения, его случаи отказа являются надстройкой.), Поэтому я даю следующие определения типа:
data FooFailure = FooFailure String
data BarFailure = BarSpecificFailure | BarFooFailure FooFailure
type FooM = ListT (EitherT FooFailure (Reader Context))
type BarM = ListT (EitherT BarFailure (Reader Context))
Я бы тогда ожидать, чтобы иметь возможность писать отношения со следующими подписями функций :
foo :: A -> B -> FooM C
bar :: B -> C -> BarM D
Моя проблема заключается в том, что при написании определения «бара», мне нужно, чтобы иметь возможность получать сообщения об ошибках от «Foo» связи и правильно представлять их в пространстве «бар». Так что я бы хорошо с функцией вида
convert :: (e -> e') -> ListT (EitherT e (Reader Context) a
-> ListT (EitherT e' (Reader Context) a
Я могу даже написать, что зверек, запустив ListT, отображение на EitherT, а затем перекомпоновки ListT (потому что это происходит, что т [а] может преобразуется в ListT ma). Но это кажется ... грязным.
Существует веская причина, по которой я не могу просто запустить трансформатор, сделать некоторые вещи под ним и в целом «вернуть его»; трансформатор, который я запускал, может иметь эффекты, и я не могу магически их уничтожить. Но есть ли способ, по которому я могу поднять функцию достаточно далеко в стеке трансформатора, чтобы выполнить какую-то работу для меня, поэтому мне не нужно писать функцию convert
, показанную выше?
Да, я бойкотировал ListT. Используйте 'pipe' для правильного ListT. Кроме того, вы можете использовать 'fmapLT' из пакета ошибок для изменения значения слева. –
Я искал 'fmapLT' ...! Но я мог бы поклясться, что это было в «любом», и не сделал этого. –
Отлично; Спасибо вам обоим. Это то, о чем мне было интересно. :) – tvynr