Как реализовать собственный экземпляр Monad, особенно для IObservable в FSharpPlus?

FSharpPlus предоставил монаду CE и несколько преобразователей монад, и я хочу использовать ReaderT<'a, IObservable<'b>> с FSharpPlus's monad CE, что требует определения экземпляра монады.

Пример желаемого кода:

      let test (x: IObservable<int>) = 
    monad {
        let! n = x
        return n + 1
    }

Ожидается, что это приведет к

      let test (v: IObservable<int>) = 
    x.SelectMany(fun n -> Observable.Return(n + 1))

Но монада CE не поддерживает из коробки, и добавление расширения, как показано ниже, в тот же модуль test функция выше не работает.

      type IObservable<'a> with
    static member Return (x: 'T) : IObservable<'T> =
        Observable.Return(x)

    static member (>>=) (x: IObservable<'T>, f: 'T->IObservable<'U>) : IObservable<'U> = 
        x.SelectMany(f)

Как определить экземпляр монады для типа IObservable?

1 ответ

На момент написания этого ответа нет способа сделать методы расширения видимыми для ограничений признаков, хотя в компиляторе F # есть давние RFC и PR для его реализации.

Итак, на данный момент, чтобы добавить тип к абстракции (например, Monad), вам нужно либо отредактировать источник типа, чтобы добавить требуемый метод, либо источник абстракции.

Первое в принципе невозможно, потому что вы можете попробовать отправить им PR, но второй вариант более осуществим в краткосрочной перспективе: отправьте PR или, по крайней мере, откройте проблему в F # +, чтобы добавить IObservable прямо как Монада.

Другие вопросы по тегам