我试图理解 Haskell 的traverse
功能并在 Javascript 中实现它,但我被卡住了。当我查看它的类型(Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
时,我明白我需要<$>
(map
在 JS 中)、<*>
(ap
在 JS 中)并且fold
为了实现它。
我想出了以下代码:
// Church encoded Identity newtype
const Ident = x => f => f(x);
const traverse = map => ft => tx => map(y => Ident(y)) (tx(x => ft(x)));
// list functor
map = f => xs => xs.map(f);
// helper
I = x => x;
// data
idA = Ident(1);
idB = Ident(null);
// and run
const r1 = traverse(map) (x => x === null ? [] : [x]) (idA); // [Ident(1)]
const r2 = traverse(map) (x => x === null ? [] : [x]) (idB); // []
console.log(r1 [0] (I)); // 1
console.log(r2); // []
由于我使用了Ident
并且Array
类型简化为(a -> [b]) -> Ident a -> [Ident b]
. traverse
在重建数据结构时运行效果。如果我没记错的话,可以在我的示例中观察到列表函子的非确定性影响。
但是应用在哪里?为什么可遍历必须是函子?我的草图不需要它们只是巧合吗?