我一直在阅读关于传感器的知识,并尝试着理解这个概念。我现在对它们有了一点了解,但在我拉小提琴的过程中,我遇到了一些非常奇怪的事情,让我目瞪口呆。我希望有人能解释一下我错过了什么。
我有两个传感器,它们的签名是:reducer -> reducer
我还有一个简单的组合函数:const compose = (f, g) => x => f(g(x))
当我合成两个传感器时:
const filterLessThanThreeAndMultiply = compose(
filteringReducer(lessThanThreePredicate),
mappingReducer(multiplyTransform)
)我希望评估是从右到左的,在这种情况下,在过滤之前应用映射转换。相反,首先应用过滤(这会给出预期的答案)。
但是f( g(x) )运行g(X)的结果的f,所以我的结果应该反映:
filteringReducer(lessThanThreePredicate)(mappingReducer(multiplyTransform)
(concatTransducer))但相反,它反映(正确地):
mappingReducer(multiplyTransform)(filteringReducer(lessThanThreePredicate)
(concatTransducer))(参见下面的代码)
为什么??!!(我怀疑一旦有人向我解释这里发生了什么,我就会在理解上取得巨大的飞跃)。
const filteringReducer = predicate => transducer => (result, input) =>
predicate(input) ? transducer(result, input) : result
const mappingReducer = transform => transducer => (result, input) =>
transducer(result, transform(input))
const compose = (f, g) => x => f(g(x))
const concatTransducer = (a, b) => a.concat([b])
const lessThanThreePredicate = x => x < 3
const multiplyTransform = x => x * 100
const filterLessThanThreeAndMultiply = compose(
filteringReducer(lessThanThreePredicate),
mappingReducer(multiplyTransform)
)
const result = [-2, -1, 0, 1, 2, 3, 4].reduce(
filterLessThanThreeAndMultiply(concatTransducer),
[]
)
console.log('result ', result) // [-200, -100, 0, 100, 200]发布于 2020-05-23 08:33:53
您可以看到filter发生在map之前(正确地),即使它们都在compose中,因为转换器的实现细节。我将通过在实现中分解传感器,然后向您展示如何使用它们来解释。
考虑map和filter的以下变体
const mapArray = fn => array => array.map(fn) // map for arrays
const filterArray = fn => array => array.filter(fn) // filter for arrays
const mapReducer = fn => reducer => (y, xi) => reducer(y, fn(xi)) // map for reducers
const filterReducer = fn => reducer => (y, xi) => fn(xi) ? reducer(y, xi) : y // filter for reducersmapArray接受一个函数element.filterArray和一个数组,并返回另一个对每个fnmapReducer应用了fn的数组;接受一个函数fn和一个数组,并返回由reducer => (y, xi) => {...}过滤的另一个数组;获取一个函数fn并返回reducer => (y, xi) => {...}
filterReducer;获取一个函数fn并返回fn现在,考虑换能器签名
reducer传感器具有以下特征: reducer ->
由于(y, xi) => {...}只是另一个reducer,这意味着mapReducer(multiplyTransform)和filterReducer(lessThanThreePredicate)都是transducers.
太棒了!现在我们知道了什么是传感器,但是我们如何使用它们呢?
附件A(无作曲)
const x100Transducer = mapReducer(x => x * 100)
const lessThanThreeTransducer = filterReducer(x => x < 3)
const concat = (y, xi) => y.concat([xi])
const finalReducerLessThanThreeThenX100ThenConcat = (y, xi) => (
lessThanThreeTransducer( // this is called with (y, xi) first
x100Transducer( // then this
concat // finally this
)
)(y, xi)
)
[1, 2, 3, 4, 5].reduce(finalReducerX100ThenConcat, []) // => [100, 200]为了设置我们的换能器,我们首先过滤x => x < 3,然后映射x => x * 100,我们必须像上面那样组成换能器lessThanThreeTransducer和x100Transducer。现在,如果我们抛出compose,你将会得到为什么一切似乎都是倒退的答案。
附件B(包含compose)
const x100Transducer = mapReducer(x => x * 100)
const lessThanThreeTransducer = filterReducer(x => x < 3)
const concat = (y, xi) => y.concat([xi])
const compose = (f, g) => x => f(g(x)) // f is lessThanThreeTransducer, g is x100Transducer
// x is concat (compare to above)
const finalComposedReducer = compose(lessThanThreeTransducer, x100Transducer)(concat)
[1, 2, 3, 4, 5].reduce(finalComposedReducer, []) // => [100, 200]实际上,finalComposedReducer和finalReducerLessThanThreeThenX100ThenConcat在算法上是等价的。那么,
为什么??!!
这是传感器的实现细节。如果你仍然对传感器感兴趣,我在here上写了更多关于它们的文章。
https://stackoverflow.com/questions/47502557
复制相似问题