简体   繁体   English

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

[英]Task, Lift and complex monads in FP-TS

I have the following code: 我有以下代码:

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 function doesn't get run, return type however is Promise 1)savePerson函数不会运行,但是返回类型是Promise

2) Fp-Ts library indicates that liftA2 type is deprecated and I should use sequenceT instead. 2)Fp-Ts库指示不建议使用liftA2类型,而应该使用sequenceT。 However from the signature it's not clear how sequenceT would apply to the parameters of buildPerson like liftA2 does 但是从签名中还不清楚,sequenceT将如何像liftA2一样应用于buildPerson的参数

3) Is there a better way to compose the functions? 3)有没有更好的方法来组合功能?

This complication is caused by needing to go between either and task and there not being a natural transformation between the two types. 这种复杂性是由于需要在任务和任务之间切换而导致的,并且两种类型之间没有自然的转换。 Why not use the existing taksEither type? 为什么不使用现有的taksEither类型? fp ts has very poor docs so I rewrote your code using a different library's taskeither (from fluture js) fp ts的文档非常差,所以我还是使用其他库的任务重写了代码(来自fluture js)

Instead heres how this would look using fluturejs (essentially task + either) 相反,这是使用fluturejs的样子(本质上是task +任一个)

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());

I wasnt able to scan the docs and figure out what these functions are called in fp-ts's implementation but Im sure they all exist. 我无法扫描文档并找出这些功能在fp-ts的实现中被称为什么,但我确定它们都存在。 Flutures parallel function takes a list of Futures and returns a future of a list, this behavior is essentially concat and should exist in fp-ts's taskeither because its required to be implemented on monads Flutures并行函数获取一个Futures列表并返回一个list的Future,此行为本质上是concat,应该在fp-ts的任务中存在,因为它必须在monads上实现

Futhermore, if you redesigned the repo class and have its methods return taskeithers, you will further simplify your code. 此外,如果您重新设计了repo类并使其方法返回task,那么您将进一步简化代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM