2

试图弄清楚如何使用 fp-ts 对多个案例进行建模。不确定我对这个操作的心智模型是否应该在 fp-ts 中有所不同,是否我找不到合适的功能来使用,或者这样的功能不存在。

作为参考,https ://ramdajs.com/docs/#cond(Lodash中的相同签名+行为)

示例案例是加载/加载状态,或在枚举上拆分案例。例如,

enum abcd {a,b,c,d}

const getCaseResult = cond([
  [is(a), getResultA],
  [is(b), getResultB],
  [is(c), getResultC],
  [is(d), getResultD],
])

getCaseResult('a') // returns result of getResultA('a')
4

1 回答 1

0

我对 Ramda 的类型定义做了一些研究,因为我很好奇如果谓词函数实际上是类型保护,它们是如何处理类型的。事实证明,他们不使用类型保护来缩小类型。 请参阅DefinitelyTyped 代码

顺便说一句,那里的评论实际上使他们给出的类型定义无效:

如果没有任何谓词匹配,则 fn 返回 undefined。

但是类型声明它返回一个Rnot R | undefined。我尝试cond使用实用程序使用等效类型来实现fp-ts,因为正如一些评论者指出的那样,它看起来不像fp-ts内置等效于 cond。

像这样的东西对你有用吗?

import { reduce } from "fp-ts/lib/Array";
import { alt, some, none, fold, Option } from "fp-ts/Option";
import { pipe } from "fp-ts/lib/function";

type CondPair<T extends any[], R> = [
  (...args: T) => boolean,
  (...args: T) => R
];
const cond = <T extends any[], R>(pairs: Array<CondPair<T, R>>) => (
  ...args: T
): R | undefined =>
  pipe(
    pairs,
    reduce(
      none,
      (prev: Option<R>, [pred, res]: CondPair<T, R>): Option<R> =>
        pipe(
          prev,
          alt(() => (pred(...args) ? some(res(...args)) : none))
        )
    ),
    fold(
      () => undefined,
      (r) => r
    )
  );

enum abcd {
  a,
  b,
  c,
  d
}

const is = <T>(t: T) => (x: unknown) => t === x;

function isResultA(a: abcd) {
  return 1;
}
function isResultB(b: abcd) {
  return 2;
}
function isResultC(c: abcd) {
  return 3;
}
function isResultD(d: abcd) {
  return 4;
}

const getCaseResult = cond([
  [is(abcd.a), isResultA],
  [is(abcd.b), isResultB],
  [is(abcd.c), isResultC],
  [is(abcd.d), isResultD]
]);

for (let x of [abcd.a, abcd.b, abcd.c, abcd.d]) {
  console.log(getCaseResult(x));
} // Logs 1, 2, 3, 4 respectively
于 2022-03-06T04:05:08.840 回答