() -> (() -> a)
- sequence (IEnumerable)
with arrows reversed:
(a -> ()) -> ()
- observable (IObservable)
Everything is fine and we have duality between pull and push. In particular, () -> a
is dual to a -> ()
.
() -> (() -> IO a)
- async sequence (AsyncSeq in F#, Source in scalaz-stream)
with arrows reversed:
(IO a -> ()) -> ()
- dual of async sequence, but is not async observable!
Note the co-Kleisli IO a -> ()
.
An async observable would be:
(a -> IO ()) -> ()
- this is async observable
Note the Kleisli a -> IO ()
.
The issue is that an async observable makes use of Kleisli and so cannot be dual to async sequence which also uses Kleisli. In particular, () -> IO a
is not dual to a -> IO ()
. More technically, this is an issue of variance.
The reason this is interesting is that for an Rx model to have async observers, it can no longer be dual to async sequences. This is not in itself a problem but raises some concerns for implementing async observers. Intuitively, if observers represent a push-based or data-driven source, then it may not make sense for observers to be async.