lte pss是什么
if you have this 3 things T, concat and empty together, you have a monoid:
如果您拥有这3个事物T,并同时排空 ,那么您就有一个monoid:
T — Set of values for example set of strings, or set of array etc,
T —一组值,例如字符串组或数组组等,
concat — Function which takes 2 values from that set T, and returns new value which is in the same set T, such that this function is Associative.
concat —函数,该函数从该集合T中获取2个值,并返回位于同一集合T中的新值,以使该函数具有关联性。
empty — special value from the set T such that it is an identity element for that function concat.
空—来自集合T的特殊值,以使其成为该函数concat的标识元素。
We can express this in typescript like this:
我们可以这样在打字稿中表达这一点:
type Monoid<T> = { concat: (a:T, b:T) => T; empty: T;}And we can have this laws/tests that must hold true for valid monoids:
我们可以拥有以下法律/测试,这些法律/测试必须适用于有效的类半身像:
const associativity = <T>(M: Monoid<T>, a:T, b:T, c: T) => deepEqual( M.concat(a, M.concat(b, c)), M.concat(M.concat(a, b), c)) )const leftIdentity = <T>(M: Monoid<T>, a:T) => deepEqual( M.concat(a, M.empty), a )const rightIdentity = <T>(M: Monoid<T>, a:T) => deepEqual( M.concat(empty, M.a), a )The fact that you can refactor a * (b * c) into a * b * c and be sure that result will not change, or the reason you can write a + b + c and don’t care if you even use parentheses at all, is + and * are associativity. The reason you would refactor a + 0 or a * 1 to just a is because 0 is identity to the + operator as well as1 for *. Once you know something is a monoid you know that if you want to concat multiple values you can group in multiple batches execute them on multiple threads/workers and combine them. You can implement generic functions for such structures my favorite is fold
您可以将a * (b * c)重构为a * b * c并确保结果不会改变的事实,或者您可以写a + b + c的原因也不在乎是否在$处使用括号全部是+和*是关联性。 究其原因,你会重构a + 0或a * 1 ,只是a是因为0是身份到+运营商以及1对* 。 一旦知道某物是一个monoid,便知道如果要合并多个值,可以将其分为多个批处理,在多个线程/工作者上执行它们并将它们组合在一起。 您可以为此类结构实现通用功能,我最喜欢fold
function fold<T>(M: Monoid<T>, array: T[]): T { return array.reduce(M.concat, M.empty)}fold(stringMonoid, ["a","b","c"]) === "abc"fold(arrayMonoid, [["a"],["b"],["c"]]) === ["a","b","c"]fold(numberAdditiveMonoid, [1,2,3]) === 6fold(numberMultiplicativeMonoid, [2,3,4]) === 24one of the most obvious instance are for String and Array
最明显的实例之一是String和Array
Note that for some type T there can exist more then one Monoid<T>
请注意,对于某些类型T ,可以存在一个Monoid<T>
Most well known of such types is Number
这种类型中最著名的是Number
and
和
const numberMultiplicativeMonoid: Monoid<number> = { concat: (a:number, b:number):number => a * b, empty: 1,}// Associativitya * (b * c) === (a * b) * c// Identity 1 * s === ss * 1 === sOrdering is my favorite, it’s very nice and useful, when you want to sort array of some records based on many properties.
当您要基于许多属性对某些记录的数组进行排序时,排序是我的最爱,非常好用。
type Ordering = -1 | 0 | 1const orderingMonoid: Monoid<Ordering> = { concat: (a: Ordering, b: Ordering): Ordering { return a === 0 ? b : a }, empty: 0}const users = [ { firstName:"Alisa", lastName:"Able" } , { firstName:"Bob", lastName:"Able" } , { firstName:"Alisa", lastName:"Brown" } , { firstName:"Bob", lastName:"Brown" } , { firstName:"Alisa", lastName:"Bold" } , { firstName:"Bob", lastName:"Bold" } ]users.sort( (a,b) => orderingMonoid.concat( a.firstName.localeCompare(b.firstName), a.lastName.localeCompare(b.lastName) ))// users now will be[ { "firstName": "Alisa", "lastName": "Able" }, { "firstName": "Alisa", "lastName": "Bold" }, { "firstName": "Alisa", "lastName": "Brown" }, { "firstName": "Bob", "lastName": "Able" }, { "firstName": "Bob", "lastName": "Bold" }, { "firstName": "Bob", "lastName": "Brown" } ]users.sort( (a,b) => orderingMonoid.concat( a.lastName.localeCompare(b.lastName), a.firstName.localeCompare(b.firstName) ))// users now will be[ { "lastName": "Able", "firstName": "Alisa"}, { "lastName": "Able", "firstName": "Bob"}, { "lastName": "Bold", "firstName": "Alisa"}, { "lastName": "Bold", "firstName": "Bob"}, { "lastName": "Brown", "firstName": "Alisa"}, { "lastName": "Brown", "firstName": "Bob"}]// or you can do thisusers.sort((a,b) => fold( orderingMonoid, [ a.lastName.localeCompare(b.lastName) , a.firstName.localeCompare(b.firstName) , a.points - b.points , a.someNumberField - b.someNumberField ]))if you look closely at the orderingMonoid.concat you would notice that it can be implemented as a || b. Which means you can write this code while fully understanding how ordering is a monoid and why this works:
如果仔细查看orderingMonoid.concat您会注意到它可以实现为a || b a || b 。 这意味着您可以在完全理解排序如何成为一个等分体以及为什么有效的同时编写此代码:
users.sort( (a,b) => a.lastName.localCompare(b.lastName) || a.firstName.localCompare(b.firstName) || a.points - b.points || a.someNumberField - b.someNumberField)Also, there are monoids which depend on other monoids, for example Function and Record
另外,还有一些Monoid取决于其他Monoid,例如Function和Record
Function from Number to String is a monoid because String is a monoid:
从Number到String的函数是一个monoid,因为String是一个monoid:
type NumToStr = (n: number) => stringconst numToStrMonoid: Monoid<NumToStr> = { concat: (a:NumToStr, b:NumToStr): NumToStr => n => { return stringMonoid.concat(a(n),b(n)) }, empty: () => stringMonoid.empty,}const a = x => (x*2).toString()const b = x => (x*8).toString()const c = x => (x*9).toString()numToStrMonoid.append(a, numToStrMonoid.append(b,c))// is equivalent tonumToStrMonoid.append(numToStrMonoid.append(a,b),c))// is equivalent to(x) => a(x).concat(c(x) .concat(d(x)))// is equivalent to(x) => (a(x).concat(c(x))).concat(d(x))Also, If all fields of a some Record/Object R are monoids, then there exists monoid instance for this R:
同样,如果某个Record / Object R的所有字段都是monoid,则存在该R的 monoid实例:
type Stats = {age: number, height: number, weight: number}const numToStrMonoid: Monoid<Stats> = { concat: (a:Stats, b:Stats):Stats => ({ age: numberAdditiveMonoid.concat(a.age, b.age) , height: numberAdditiveMonoid.concat(a.height, b.height) , weight: numberAdditiveMonoid.concat(a.weight, b.weight) }), empty: { age: numberAdditiveMonoid.empty , height: numberAdditiveMonoid.empty , weight: numberAdditiveMonoid.empty },}Cheers 🎉
干杯🎉
翻译自: https://medium.com/@safareli/pss-ordering-is-a-monoid-61a4029387e
lte pss是什么
相关资源:TD LTE PSS Algorithm