Type level function for tracking observable behavior

Hey All.
Working on my Rxjs observable bindings, Im uncovering lots of weird behavior in observables that i hope to track in types. For example, Rxjs talks about observables being “hot” or “cold” which to some degree means that the observable emits values immediately on connection. So to reflect that in types i was thinking like:

type value<'a>
type void
type observable<'first> // first is either value<'a> or void

Next there are operators that can be applied to single observables, mostly they would pass through \firsttype but there is alsostartsWith` that would produce an observable with value<'a>. There are also functions like “withLatestFrom” or “merge2” that can take multiple observables, and then the output first value is a function of two first types…

let x: observable<value<int>>
let x2: observable<value<int>>
let y: observable<void>

let mergeX = merge2(x, x2) // Will be first value<'a>
let mergeXy = merge2(x, y) // Will be void

I think I have to make separate instances of each combinator to handle the different combinations, which could work, but then there are combinators that take an array of observables…

let mergeAll = mergeAll([x, x2, y])

I think the Rescript formal answer is “dont” but…how would you do this?

I have half been wondering it polyvariants could do this if we had subtraction from pv types. Using PV like a row type would be rad.

Thanks
A

You want HKT or dependent type?

I think there’s no way to model it fully, so I’ll quickly compromise.

If you can accept adding some runtime for it then may be possible to manage the transformation explicitly by introducing GADT like


type rec kind<t> =
  | Int_val(int): kind<value<int>>
  | ...

My guess is that merging an observable means you’ll eventually need a tag in the observer. It makes sense to have a runtime.

can you give more in that example? I love a GADT, but is that supposed to be the typing for observables themselves?

Thanks
A

No. I meant you need to box you parameters and generalize observer side, not observable itself.