通过c#代码的合成,我最终得到了一个类型
IObservable<Maybe<IObservable<T>>> events;
其中Maybe是可选项单子,IObservable是响应单子。
现在我想把它转换成
IObservable<Maybe<T>> flatEvents;
我认为表达了差不多同样的东西。注意,我想保留maybe所包含的"nothing to see"事件。我不想把它完全扁平化,这样我只看到当T的实例可用时的事件。
经过一些尝试和错误,我发现我可以通过
进行转换var flatEvents = events
.Select(p=>p.Select(q=>q.Select(v=>v.ToMaybe()))
.Else(Observable.Return(None<T>.Default)))
.Switch();
,其中None<T>.Default
返回一个空的Maybe<T>
。
T Maybe<T>.Else(T v)
提取选项单子中包含的值,如果没有,则提供替代值。
考虑到命名事物是CS最难的事情,我正在为这个平坦算子寻找一个名字。我不是一个haskell程序员,但我确定我没有发明任何东西,这是一种常见的投影。这有什么名字吗?
我发现通过纯粹考虑类型,独立于任何特定的单子,更容易弄清楚你的设计是什么。
你想要一个类型为:
的函数:: 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
是可遍历的,那么它的类型几乎是正确的以及Monad):
> :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或者某物但也许它不需要名字