#c# #functional-programming #system.reactive #monads #naming
#c# #функциональное программирование #system.reactive #монады #именование
Вопрос:
Благодаря композиции в моем коде на C # я получил тип
IObservable<Maybe<IObservable<T>>> events;
где Maybe — это option monad, а IObservable — реактивная монада.
Теперь я хочу преобразовать это в
IObservable<Maybe<T>> flatEvents;
что, я думаю, выражает практически то же самое. Обратите внимание, что я хочу сохранить событие «ничего не видеть», воплощенное в maybe . Я не хочу полностью сглаживать его, чтобы я видел события только тогда, когда доступен экземпляр T .
После небольшого количества проб и ошибок я обнаружил, что могу выполнить преобразование с помощью
var flatEvents = events
.Select(p=>p.Select(q=>q.Select(v=>v.ToMaybe()))
.Else(Observable.Return(None<T>.Default)))
.Switch();
где None<T>.Default
возвращает a Maybe<T>
, которое является пустым.
T Maybe<T>.Else(T v)
извлекает содержащееся значение в параметрической монаде и, если его нет, предоставляет альтернативу.
Учитывая, что называть вещи сложнее всего, это CS, я ищу имя для этого оператора выравнивания. Я не программист на haskell, но я уверен, что я здесь ничего не изобрел, и это какая-то общая проекция. Есть ли имя для этого?
Комментарии:
1. Просто любопытно, что такое, возможно, наблюдаемое? Можно ли заменить это на Observable. Пустой <T> , или это потеряет смысл в вашем домене?
Ответ №1:
Мне легче понять, что представляет собой ваш дизайн, просто рассматривая типы, независимо от какой-либо конкретной монады.
Вам нужна функция типа:
:: Observable (Maybe (Observable a))
->
Observable (Maybe a)
где Maybe — это монада, а Observable — монада.
Поскольку монады являются общим интерфейсом, мы действительно имеем:
:: (Monad m, Monad t) => m (t (m a)) -> m (t a)
Из этого типа мы можем видеть, что это своего рода соединение, распределенное по
внутренней монаде m
.
Некоторые связанные типы:
join :: Monad m => m (m a) -> m a
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
На самом деле, это очень похоже на последовательность fmap над внутренним компонентом, за которой следует
соединение, которое имеет почти правильный тип, предполагая t
, что оно проходимо (а
также монада):
> :t join . fmap T.sequence
:: (Monad m, Functor m, Traversable t)
=> m (t (m a)) -> m (t a)
Итак, вот наш тип. m (t (m a))
Для m (t a)
. Идеальный.
Так что, если вам действительно нужно назвать это, это будет joinSequence или что-то в этом роде. Но, возможно, ему не нужно имя.