[英]Remove Options from array of items in fp-ts
Say I have the following types:假设我有以下类型:
type ValidatedInput = Readonly<{
id: string
}>
type GetStructures = (id: string) => TaskEither<ServiceError, ReadonlyArray<SomeStructure>>
type GetOtherStructures = (ids: ReadonlyArray<string>) => TaskEither<ServiceError, ReadonlyArray<SomeOtherStructure>>
type LookupThings = (initialInput: ReadonlyArray<SomeStructure>, additionalInput: ReadonlyArray<SomeOtherStructure>) => TaskEither<ServiceError, ReadonlyArray<Option<ResponseType>>>
export type Deps = Readonly<{
getStructures: GetStructures
getOtherStructures: GetOtherStructures
lookupThings: LookupThings
}>
export type Ctx<T> = ReaderTaskEither<Deps, Error, T>
And the following error handling helper:以及以下错误处理助手:
type Code = 'INVALID_ENTITY' | 'INVALID_API_KEY'
export const fromCode = (code: Code): Error => ({
tag: 'validation',
code
})
I then create a function like so:然后我像这样创建一个 function :
const constructFullData = (input: ValidatedInput): Ctx<ReadonlyArray<Option<ResponseType>>> => (
(deps: Deps): TE.TaskEither<Error, ReadonlyArray<Option<ResponseType>>> => (
pipe(
deps.getStructures(input.id),
TE.map((structs) => pipe(
deps.getOtherStructures([structs[0].higherOrderId]),
TE.chain(otherStructs => pipe(
deps.lookupThings(structs, otherStructs),
TE.chain(results => {
if (results.filter(isNone).length !== results.length) {
return TE.left(fromCode('INVALID_ENTITY')) // I'm not sure what a better way to filter this is. Ideally the return type of this function wouldn't have an Option in it
} else {
return TE.right(results)
}
})
))
)),
TE.flatten
)
)
)
This all compiles just fine, but what I really want is to return an array with none's filtered out, and raise the appropriate error if there is a none!这一切都编译得很好,但我真正想要的是返回一个没有过滤掉的数组,如果没有则引发适当的错误!
The naive approach is to change the return of the Right path to:天真的方法是将 Right 路径的返回更改为:
return TE.right(results.map(u => u.value))
But this does not compile, throwing the following error:但这不会编译,抛出以下错误:
Property 'value' does not exist on type 'None'.
64 return TE.right(usagesWithDrones.map(u => u.value))
How can apply this kind of filtering?如何应用这种过滤?
What about folding the list of options into an either?将选项列表折叠成一个呢? Something like:
就像是:
import * as TE from "fp-ts/TaskEither";
import * as ROA from "fp-ts/ReadonlyArray";
import * as T from "fp-ts/Task";
import * as E from "fp-ts/Either";
import * as O from "fp-ts/Option";
import { pipe } from "fp-ts/pipeable";
import { constant, flow, Lazy } from "fp-ts/lib/function";
const value = TE.right<"ThisErrorDoesntExist", readonly O.Option<number>[]>(
ROA.of(O.some(42))
);
const arrayOfNumbersMonoid = ROA.getMonoid<number>();
type Result = E.Either<"FoundNoneInList", readonly number[]>;
const rightEmptyListOfNumbers: Result = E.right([]);
const leftFoundNoneInList: Lazy<Result> = constant(E.left("FoundNoneInList"));
const reducer = (acc: typeof rightEmptyListOfNumbers, next: O.Option<number>) =>
pipe(
acc,
E.chain((numbers) =>
pipe(
next,
O.fold(
leftFoundNoneInList,
flow(ROA.of, (n) => arrayOfNumbersMonoid.concat(numbers, n), E.right)
)
)
)
);
const result = pipe(
value,
T.map(E.chainW(ROA.reduce(rightEmptyListOfNumbers, reducer)))
);
The easiest way to remove options from an array is to use the compact function (see a simple example below).从阵列中删除选项的最简单方法是使用紧凑型 function(参见下面的简单示例)。 The compact function is present in most of the fp-ts libs.
紧凑型 function 存在于大多数 fp-ts 库中。
import { Option, some, none } from "fp-ts/lib/Option"
import { compact } from "fp-ts/lib/Array"
const initialArray = [1, 2, 3, 4, 5, 6, 7]
const arrayWithOptions: Option<number>[] = initialArray.map((el) => {
if (el % 2 === 0) return some(el)
else return none
})
const finalArray: number[] = compact(arrayWithOptions)
console.log(finalArray)
The console log will print [2,4,6].控制台日志将打印 [2,4,6]。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.