通过我的C#代码中的组合,我最终得到了一个类型
IObservable<Maybe<IObservable<T>>> events;
其中Maybe是monad选项,IObservable是被动monad。
现在我想将其转换为
IObservable<Maybe<T>> flatEvents;
我认为表达了几乎相同的东西。注意我想保留可能体现的“无所事事”事件。我不想完全展平它,所以我只能在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)
提取选项monad中包含的值,如果没有,则提供替代值。
考虑到命名事情是最难的事情CS我正在寻找这个扁平化运算符的名称。我不是一个haskell程序员,但我确信我没有在这里发明任何东西,这是一种常见的投影。这有名字吗?
答案 0 :(得分:5)
通过纯粹考虑类型,我发现更容易弄清楚你的设计是什么,独立于任何特定的monad。
你想要一个类型的函数:
:: Observable (Maybe (Observable a))
->
Observable (Maybe a)
其中Maybe是monad,Observable是monad。
由于monad是一个通用接口,我们确实有:
:: (Monad m, Monad t) => m (t (m a)) -> m (t a)
从这种类型我们可以看到它是一种分布在上面的连接
内在的monad m
。
一些相关类型:
join :: Monad m => m (m a) -> m a
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
事实上,它看起来非常像内部组件上的fmap序列,其次是
通过连接 - 具有几乎正确的类型,假设t
在Traversable中(如
以及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或者 一些东西。但也许它不需要名字。