2

我有以下代码:

import { Task, task } from "fp-ts/lib/Task"
import { Either, left, right } from "fp-ts/lib/Either"
import { curry } from "fp-ts/lib/function"
import { liftA2 } from "fp-ts/lib/Apply"
import { Repo } from "./repo"

const buildPerson = curry((name: string, age: number): Either<Error, any> => {
    if (name !== undefined && age !== undefined) {
        return right({ name, age })
    } else {
        return left(Error("Missing parameter"))
    }
})

const validatePerson = (person: any): Either<Error, any> => {
    if ( person.age < 18) {
        return left(Error("Too Young")) 
    } else {
        return right(person)
    }
}

const getNameFromRepo = (repo: Repo): Task<string> => {
    return new Task(
        () => repo.getName()
    )
}

const getAgeFromRepo = (repo: Repo): Task<number> => {
    return new Task(
        () => repo.getAge()
    )
}

const savePerson = curry((person:any, repo: Repo): Task<void> => {
    return new Task(
        () => {
            console.log(person)
            return repo.setPerson(person)
        }
    )
})

const hello = async () => {
    const repo = new Repo()

    await liftA2(task)(buildPerson)(getNameFromRepo(repo))(getAgeFromRepo(repo))
    .map(
        (e) => e.chain(
            (p) => validatePerson(p)
        )
    )
    .map(
        (e) => e.fold(
            (l) => console.log(l),
            (r) => savePerson(r)
        )
    )
    .run()
}

hello()

1) savePerson 函数没有运行,但是返回类型是 Promise

2) Fp-Ts 库表明不推荐使用 liftA2 类型,我应该改用 sequenceT。然而,从签名中不清楚 sequenceT 将如何应用于 buildPerson 的参数,如 liftA2

3)有没有更好的方法来组合功能?

4

1 回答 1

0

这种复杂性是由于需要在任一个和任务之间进行,并且这两种类型之间没有自然的转换。为什么不使用现有的 taksEither 类型?fp ts 的文档很差,所以我使用不同的库的 taskeither 重写了您的代码(来自 Fluture js)

相反,这是使用fluturejs的外观(本质上是任务+)

import * as Future from 'fluture';

const buildPerson = (name, age) =>
    name !== undefined && age !== undefined
        ? Future.of({ name, age })
        : Future.reject(Error("Missing parameter"));

const validatePerson = ({ name, age }) =>
    age < 18
        ? Future.reject(Error("Too Young"))
        : Future.of({ name, age });

const getNameFromRepo = (repo: Repo) => {
    return Future.Future((reject, resolve) =>
        resolve(repo.getName()));
}

const getAgeFromRepo = (repo: Repo) => {
    return Future.Future((reject, resolve) =>
        resolve(repo.getAge()));
}

const savePerson = (repo: Repo) => (person) => {
    return Future.Future((reject, resolve) =>
        resolve(repo.setPerson(person)));
}
const hello = (repo: Repo) =>
    Future.parallel(1, [
        getNameFromRepo(repo),
        getAgeFromRepo(repo),
    ])
        .chain(([name, age]) => buildPerson(name, age))
        .chain(validatePerson)
        .chain(savePerson(repo))
        .fork(
            (err) => console.warn('err', err),
            () => console.log('it worked!'),
        );

hello(new Repo());

我无法扫描文档并弄清楚这些函数在 fp-ts 的实现中被称为什么,但我确信它们都存在。Flutures 并行函数接受一个 Futures 列表并返回一个列表的未来,这种行为本质上是 concat 并且应该存在于 fp-ts 的任务中,因为它需要在 monads 上实现

此外,如果您重新设计了 repo 类并让它的方法返回 taskeithers,您将进一步简化您的代码。

于 2019-07-11T07:49:08.717 回答