gpt4 book ai didi

javascript - 如何编写TaskT Monad Transformer来组合异步计算和其他效果?

转载 作者:行者123 更新时间:2023-12-02 23:13:45 25 4
gpt4 key购买 nike

我将 monad 转换器构造为 chain 的变体/of需要一个附加参数 - 外部 monad 的类型目录:

const None =
({runOption: null, tag: "None", [Symbol.toStringTag]: "Option"});

const Some = x =>
({runOption: x, tag: "Some", [Symbol.toStringTag]: "Option"});

const optOfT = of => x => of(Some(x));

const optChainT = ({chain, of}) => fmm => mmx =>
chain(mx => {
switch (mx.tag) {
case "None": return of(None);
case "Some": return fmm(mx.runOption);
}
}) (mmx);

const arrOf = x => [x];

const arrChain = fm => xs =>
xs.reduce((acc, x) => arrPushFlat(acc) (fm(x)), []);

const arrPushFlat = xs => ys => {
ys.forEach(x =>
xs.push(x));

return xs;
};

const xs = [Some("foo"), None, Some("bar")];

console.log(
optChainT({chain: arrChain, of: arrOf})
(s => [Some(s.toUpperCase())]) (xs)); // [Some("FOO"), None, Some("BAR")]

所以基本上,变压器是两个 monad 的手写组合,即它需要两个 monad 并返回一个新的复合 monad,因此它本身是可组合的。欢迎使用可组合效果。

但是当懒惰出现时,我无法将注意力集中在 monad 转换器上。如果我想为 [Task<Option<a>, Error>] 创建一个 monad 转换器怎么办? ?我需要一个用于异步任务的变压器,即 tChainT ,但是这个运算符会是什么样子?

这是一个机械实现(据我所知)说明了为什么 monad 不能以一般方式组合:

const tChainT = ({chain, of}) => fmm => mmx =>
chain(mx =>
tChain(fmm) (mx) // A
) (mmx);

线路A返回 Task当运行时最终会产生 ArrayTaskOption s 然后将被传递到给定的延续。但我需要立即得到结果。

这是我的 Task 的一部分与问题相关的实现:

const Task = k =>
({runTask: (res, rej) => k(res, rej), [Symbol.toStringTag]: "Task"});

const tChain = fm => mx =>
Task((res, rej) => mx.runTask(x => fm(x).runTask(res, rej), rej));

const tOf = x => Task((res, rej) => res(x));

最佳答案

您问题中的 tChainT 函数无法按预期工作,因为它的类型错误。

const tChainT = ({chain, of}) => fmm => mmx =>
chain(mx =>
tChain(fmm) (mx) // A
) (mmx);

// can be simplified to

const tChainT = ({ chain }) => fmm => chain(tChain(fmm));

// tChain :: (a -> Task e b) -> Task e a -> Task e b
// |______| |____|
// | |
// chain :: Monad m => (a -> m b) -> m a -> m b
// _|__ _|__ __|___ _|__
// | | | | | | | |
// tChainT :: Monad (Task e) => (a -> Task e b) -> Task e (Task e a) -> Task e b

来自your answertChainT函数类型也错误。

// tChainT :: Monad m => (a -> Task e b) -> m (Task e a) -> m (Task e b)
const tChainT = ({chain, of}) => fm => mmx =>
chain(mx =>
of(tChain(fm) (mx))) (mmx); // ***A***

请注意,fm 的返回类型是 Task e b,而不是 m (Task e b)。因此,tChainT 不会返回有效的单子(monad)绑定(bind)函数。事实上,不可能创建 Monad m => (a -> m (Task e b)) -> m (Task e a) -> m (Task e b) 类型的函数,因为 m (Task e a)TaskT e monad 转换器的错误结构。正确的结构如下。

// newtype TaskT e m a = TaskT { runTaskT :: (a -> m (), b -> m ()) -> m () }
const TaskT = runTaskT => ({ [Symbol.toStringTag]: "TaskT", runTaskT });

// tChainT :: (a -> TaskT e m b) -> TaskT e m a -> TaskT e m b
const tChainT = f => m => TaskT((res, rej) =>
m.runTaskT(x => f(x).runTaskT(res, rej), rej));

// tOfT :: a -> TaskT e m a
const tOfT = x => TaskT((res, rej) => res(x));

请注意,tChainTtOfT 分别与 tChaintOf 具有相同的实现。这是因为 TaskT 的底层 monad 来自解析和拒绝处理程序。因此,延续机制会为我们处理它。毕竟任务只是 Cont并有额外的拒绝继续。

关于javascript - 如何编写TaskT Monad Transformer来组合异步计算和其他效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57239183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com