Как реализовать собственный экземпляр 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
прямо как Монада.