У меня есть монадическая структура данных, которая выглядит следующим образом:
export abstract class Data<A> {
static initial<A>(): Data<A> {
return new Initial<A>()
}
static failed<A>(error?: any): Data<A> {
return new Failed<A>(error)
}
static loaded<A>(value: A): Data<A> {
return new Loaded<A>(value)
}
static loading<A>(): Data<A> {
return new Loading<A>()
}
static getData<A>(data: Loaded<A>): A {
return data.getData()
}
constructor(public readonly kind: Kind) {}
abstract map<B>(f: (a: A) => B): Data<B>
abstract chain<B>(f: (a: A) => Data<B>): Data<B>
abstract flatMap<B>(f: (a: A) => Data<B[]>): Data<B>[]
}
Где Initial
, Failed
, Loaded
и Loading
- это четыре разные "формы" моего типа.
Иногда в моем коде я получаю Data<A>[]
, который я хотел бы отфильтровать, основываясь на условии A
.Моя текущая реализация такова:
static filter<A>(data: Data<A>[], pred: (a:A) => boolean): Data<A>[] {
return data.filter(datum => {
if(datum.isLoaded()) {
return pred(datum.data)
}
return false
})
}
Большая часть кода использует цепочечные методы, такие как:
data.map(...).filter(...).doThis().doThat()
, но из-за static
иногда порядок может запутаться:
Data.filter(data.map(...).flatMap(...), myPredicate).map(...).doThis(...) ........
Мне было интересно, есть ли способ сделать эту функцию нестатичной и использовать «плавный» стиль объединения методов?
Должен ли я расширить прототип массива для этого?