Существует ли общее функциональное имя программирования для следующей операции

#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 или что-то в этом роде. Но, возможно, ему не нужно имя.