我可以使用带有effect-ts的自定义monad吗?

问题描述 投票:0回答:1

我经常在 TypeScript 中使用 monad 并从头开始定义它们,并且总是错过 HKT,因此我可以定义适用于所有 monad 的通用函数,例如通用

map
或某种类似 Haskell 的 do 表示法。

我正要开始深入研究 fp-ts,但我刚刚发现它正在与 Effect-ts 合并,这看起来是一个非常简洁的包,据我所知,它使用了一种更好的方式来编码 HKT。

在我看来,

Effect
是几个单子的组合,我想知道是否有一种方法可以在那里插入我自己的单子。例如,我希望能够使用数组 monad,这样我就可以从一个数字数组构造一个
Effect<number, ...>
,当我调用
Effect.flatMap
时,这些数字会被展平。如果我没记错的话,只要有办法使用 Effect 作为延续 monad,我应该能够 模拟所有其他 monad ,但 Effect 看起来并不包含延续 monad。我没有太多关于
Effect.runCallback
的信息,但在我看来,回调仅在评估完成时调用一次,而真正的延续需要一种多次接收回调的方法。

所以我想知道我是否遗漏了一些东西,或者也许我应该使用 fp-ts 来代替,因为我主要对使用自己的 monad 感兴趣,而不是对 Effect 提供的无数实用函数感兴趣。

typescript functional-programming higher-kinded-types fp-ts effect-ts
1个回答
0
投票

是的,您可以使用effect-ts 来定义自定义monad。 由于项目合并,我最近从 fp-ts 转移到effect-ts。 Effect-ts 中的操作略有不同,您需要在标准

@effect/typeclass
包之上安装
effect
。 目前没有太多关于如何使用这些类与 fp-ts 的文档,但有足够的相似之处,可以让您了解 fp-ts 的工作原理是很好的背景阅读。

effect-ts 中的 HKT 类型必然更复杂,关键区别在于 fp-ts 使用中央注册表 (URItoKind) 作为 HKT 的映射,而effect-ts 使用更加分散的方法,其中每个 TypeLambda 都带有自己的实现Kind 应该如何解释它 - 请参阅下面的文章,这对解释非常有帮助。

它不直接处理 monad,但下面的示例展示了如何采用常规 Functor(effect-ts 中的

Covariant
)并为它们编写通用函数 - 如果您深入研究,也可以使用 monad 实现相同的功能在effect-ts下的typeclasses目录中。

我还在下面引用了我正在编写的一个存储库,其中显示了effect-ts中的许多经典LYAH问题 - 它很混乱,而且我经常偏离路线,因为我发现在effect-ts中需要坚持一些有趣的东西 -但这里有很多在effect-ts 中使用 HKT 和各种 fp 结构的例子。 我希望在下周左右添加来自 LYAH 的“Pierre's”monad 示例或类似的示例!

// -*- compile-command: "npx ts-node optional-effect.ts" -*-

import { Covariant as OptionCovariant } from "@effect/typeclass/data/Option";
import { Covariant as ArrayCovariant } from "@effect/typeclass/data/Array";
import { some } from "effect/Option";
import type { Covariant } from "@effect/typeclass/Covariant";
import type { Kind, TypeLambda } from "effect/HKT";

// Generic increment function using the generic Covariant interface
function increment<F extends TypeLambda>(
  covariant: Covariant<F>,
  fa: Kind<F, unknown, unknown, unknown, number>
): Kind<F, unknown, unknown, unknown, number> {
  return covariant.map(fa, (x) => x + 1);
}

// Use the Option-specific Covariant instance
const someValue = some(5);
const incremented = increment(OptionCovariant, someValue);
console.log(incremented); // Output: Some(6)

const arrayValue = [1,2,3,4]
const arrayIncremented = increment(ArrayCovariant, arrayValue)
console.log(arrayIncremented); // [2,3,4,5]

参考:

© www.soinside.com 2019 - 2024. All rights reserved.