M-N*_*M-N 5 functional-programming either typescript
我最近一直在试验 TypeScript,我正在尝试实现一些基本的 monad。我已经有了一个功能合理的 Maybe(至少使用与下面的任何一种方法相同的方法),但是由于与类型相关的原因,我不太明白任何一种。
我的更高级类型的打字策略是从这篇文章中借用的:https ://medium.com/@gcanti/higher-kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe 。我知道有些库已经拥有所有这些 monad 和其他 FP 好东西,但是像这样实现它们是我尝试更深入地学习 TypeScript 的方式。
declare module './HKT' {
interface TypeIDtoHKT2<E, A> {
Either: Either<E, A>;
}
}
export const TypeID = 'Either';
export type TypeID = typeof TypeID;
export class Left<E> {
readonly _F!: TypeID;
readonly _A!: E;
readonly _tag: 'Left' = 'Left';
constructor(readonly left: E) {}
static of<E, A>(e: E): Either<E, A> {
return new Left(e);
}
map<A, B>(f: (a: A) => B): Either<E, B> {
return this;
}
chain<A, B>(f: (a: A) => Either<A, B>): Either<E, B> {
return this;
}
ap<A, B>(f: Either<A, (a: A) => B>): Either<E, B> {
return this;
}
}
export class Right<A> {
readonly _F!: TypeID;
readonly _A!: A;
readonly _tag: 'Right' = 'Right';
constructor(readonly right: A) {}
static of<A, E>(a: A): Either<E, A> {
return new Right(a);
}
map<E, B>(f: (a: A) => B): Either<E, B> {
return Right.of(f(this.right));
}
chain<E, B>(f: (a: A) => Either<E, B>): Either<E, B> {
return f(this.right);
}
ap<E, B>(f: Either<E, (a: A) => B>): Either<E, B> {
if (f instanceof Left) return f;
return this.map(f.right);
}
}
export type Either<E, A> = Left<E> | Right<A>;
export const left = <E, A>(e: E): Either<E, A> => {
return new Left(e);
};
export const right = <E, A>(a: A): Either<E, A> => {
return new Right(a);
};
Run Code Online (Sandbox Code Playgroud)
当我尝试运行测试断言(例如 )时right(4).map(isEven) === true,出现以下错误:
Cannot invoke an expression whose type lacks a call signature. Type '(<E, B>(f: (a: number) => B) => Either<E, B>) | (<A, B>(f: (a: A) => B) => Either<unknown, B>)' has no compatible call signatures.
我不明白为什么这个E类型在unknown这里或者我如何让它为人所知……或者这是否是尝试做的正确的事情。任何指导表示赞赏。
问题就在这里:
export const left = <E, A>(e: E): Either<E, A> => {
return new Left(e);
};
export const right = <E, A>(a: A): Either<E, A> => {
return new Right(a);
};
Run Code Online (Sandbox Code Playgroud)
这会起作用:
console.log(isEven(3))
console.log((new Right(4)).map(isEven))
Run Code Online (Sandbox Code Playgroud)
这也将起作用:
console.log(right(3))
Run Code Online (Sandbox Code Playgroud)
但是当你尝试这样做时:
right(3).map(isEven)
Run Code Online (Sandbox Code Playgroud)
编译器变得疯狂并且无法正确绑定类型。我认为这是语言的限制。只是不要使用常量并直接使用构造函数。
| 归档时间: |
|
| 查看次数: |
2296 次 |
| 最近记录: |