3

我一直在阅读传感器并尝试掌握这个概念。我现在有点理解它们了,但是在我摆弄的过程中,我遇到了一些非常奇怪的东西,让我目瞪口呆。我希望有人能解释我所缺少的。

我有 2 个具有签名的传感器:reducer -> reducer

我还有一个简单的撰写功能:const compose = (f, g) => x => f(g(x))

当我组成​​ 2 个换能器时:

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]
4

1 回答 1

0

filter会(正确地)看到发生在 the 之前,map即使它们都在内部,因为由于sensorscompose的实现细节。我将通过分解实现中的传感器来解释,然后向您展示如何使用它们。

考虑以下变体mapfilter

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 reducers
  1. mapArray接受一个函数fn和一个数组并返回另一个fn应用于每个元素的数组。
  2. filterArray接受一个函数fn和一个数组并返回另一个由过滤的数组fn
  3. mapReducer接受一个函数fn并返回reducer => (y, xi) => {...}
  4. filterReducer接受一个函数fn并返回reducer => (y, xi) => {...}

现在,考虑换能器签名

转换器具有签名:reducer -> reducer

Given(y, xi) => {...}只是另一个减速器,这意味着mapReducer(multiplyTransform)并且filterReducer(lessThanThreePredicate)都是传感器

伟大的!所以现在我们知道了传感器是什么,但是我们如何使用它们呢?

展览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,我们必须组合我们的传感器lessThanThreeTransducerx100Transducer就像我们在上面所做的那样。现在,如果我们折腾compose,您将得到关于为什么一切似乎都倒退的答案。

展品 B(带作曲)

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在算法上是等效的。那么,

为什么??!!

这是转换器的实现细节。如果您仍然对传感器感到好奇,我会在这里写更多关于它们的信息。

于 2020-05-23T00:33:52.800 回答