FP-TS中的任务,提升和复杂单子

时间:2019-05-18 21:28:51

标签: typescript functional-programming fp-ts

我有以下代码:

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将如何像liftA2一样应用于buildPerson的参数

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

1 个答案:

答案 0 :(得分:0)

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

相反,这是使用fluturejs(本质上是任务+)之一的样子

app-db

我无法扫描文档并弄清楚这些功能在fp-ts的实现中被称为什么,但是我确定它们都存在。 Flutures并行函数获取一个Futures列表,并返回该列表的Future,此行为本质上是连续的,应该存在于fp-ts的任务中,因为它必须在monads上实现

还有,如果您重新设计了repo类并使它的方法返回任务,那么您将进一步简化代码。