如何存储Monoidal List功能链的数据? [英] How to store data of a functional chain of Monoidal List?
问题描述
这是我先前问题的高级主题:
This is an advanced topic of my prior question here:
简短的想法是
以下简单函数:
const L = a => L;
表格
L
L(1)
L(1)(2)
...
这似乎形成一个列表,但实际数据根本没有存储,所以如果需要存储[1,2]这样的数据,那么最聪明的做法是什么?任务完成了吗?
This seems to form a list but the actual data is not stored at all, so if it's required to store the data such as [1,2], what is the smartest practice to have the task done?
其中一个突出的想法来自@ user633183,我将其标记为已接受的答案(请参阅问题链接),另一个版本的curried函数也是由@MatíasFidemraizer提供。
One of the prominent ideas is from @user633183 which I marked as an accepted answer(see the Question link), and another version of the curried function is also provided by @Matías Fidemraizer .
所以这里是:
const L = a => {
const m = list => x => !x
? list
: m([...list, x]);
return m([])(a);
};
const list1 = (L)(1)(2)(3); //lazy : no data evaluation here
const list2 = (L)(4)(5)(6);
console.log(list1()) // now evaluated by the tail ()
console.log(list2())
我真正喜欢的是懒惰评价。
What I really like is it turns out lazy evaluation.
虽然给定的方法满足我提到的,但是这个函数已经失去了外部结构或者我必须使用mentiion:
Although the given approach satisfies what I mentioned, this function has lost the outer structure or I must mentiion:
const L = a => L;
形成一个列表,从根本上给我们一个 identity element <的.org / wiki / Algebraic_structurerel =nofollow noreferrer>代数结构 / a>,可能还有 Monoid 或 Magma 。
which forms list and more fundamentally gives us an algebraic structure of identity element, potentially along with Monoid or Magma.
Monoids和身份最简单的例子之一是数字和字符串
和 [数组]
$ j
One of the easiest examples of Monoids and identity is number and "Strings"
and [Array]
in JavaScript.
0 + a === a === a + 0
1 * a === a === a * 1
在字符串中,空的quoate 是标识元素。
In Strings, the empty quoate ""
is the identity element.
"" + "Hello world" === "Hello world" === "Hello world" + ""
同样适用于 [数组]
。
同样适用于 L
:
(L)(a) === (a) === (a)(L)
const L = a => L;
const a = L(5); // number is wrapped or "lift" to Type:L
// Similarity of String and Array
// "5" [5]
//left identity
console.log(
(L)(a) === (a) //true
);
//right identity
console.log(
(a) === (a)(L) //true
);
以及明显的身份不变性:
and the obvious identity immutability:
const L = a => L;
console.log(
(L)(L) === (L) //true
);
console.log(
(L)(L)(L) === (L) //true
);
console.log(
(L)(L)(L)(L) === (L) //true
);
以下内容:
const L = a => L;
const a = (L)(1)(2)(3);
const b = (L)(1)(L)(2)(3)(L);
console.log(
(a) === (b) //true
);
实现的最聪明或最优雅的方式(非常实用且无突变(无
满足3个要求: Array.push
)) L
一个简单的函数:
const L = a => L;
已经满足我们已经看到的身份法。
already satisfies the identity law as we already have seen.
虽然 L
符合身份法,但没有访问列出/累积数据的方法。
Although L
satisfies the identity law, there is no method to access to the listed/accumulated data.
(我在上一个问题中提供的答案提供了数据累积能力,但违反了身份法。)
(Answers provided in my previous question provide the data accumulation ability, but breaks the Identity law.)
懒惰评估似乎是正确的方法,因此提供更清晰的规范:
Lazy evaluation seems the correct approach, so providing a clearer specification:
const L = a => L; // needs to enhance to satisfy the requirements
const a = (L)(1)(2)(3);
const b = (L)(1)(L)(2)(3)(L);
console.log(
(a) === (b) //true
);
console.log(
(a).eval() //[1, 2, 3]
);
console.log(
(b).eval() //[1, 2, 3]
);
要求3 - Monoid联合法
除了突出的识别结构外,Monoids还满足联想法
(a * b) * c === a * b * c === a * (b * c)
这只是意味着展平列表,换句话说,结构不包含嵌套列表。
This simply means "flatten the list", in other words, the structure does not contain nested lists.
[a,[b,c]]
不好。
示例:
const L = a => L; // needs to enhance to satisfy the requirements
const a = (L)(1)(2);
const b = (L)(3)(4);
const c = (L)(99);
const ab = (a)(b);
const bc = (b)(c);
const abc1 = (ab)(c);
const abc2 = (a)(bc);
console.log(
abc1 === abc2 // true for Associative
);
console.log(
(ab).eval() //[1, 2, 3, 4]
);
console.log(
(abc1).eval() //[1, 2, 3, 4, 99]
);
console.log(
(abc2).eval() //[1, 2, 3, 4, 99]
);
这是实现3个要求的全部 L
作为一个幺半群。
That is all for 3 requirements to implement L
as a monoid.
这对函数式编程来说是一个很大的挑战,实际上我自己尝试了一段时间,但问过前面的问题,这是非常好的练习分享我自己的挑战并听取人们的意见并阅读优雅的代码。
This is a great challenge for functional programming to me, and actually I tried by myself for a while, but asking the previous questions, it's very good practice to share my own challenge and hear the people and read their elegant code.
谢谢。
推荐答案
更新
以下是@ user633183引入的标记
技术的库存版本。
Update
Here's a curried version of tag
technique introduced by @user633183.
我更换了名称标签/是要输入内容。
I replaced the name tag/is to type stuff.
const TYPE = Symbol();
const typeOf = t => x => x == null
? x
: Object.assign(x, {
[TYPE]: t
});
const isType = t => x => x == null
? false
: x[TYPE] === t;
const Foo = x => typeOf(Foo)(x);
console.log(
isType(Foo)(1) // false
, isType(Foo)([]) // false
, isType(Foo)({}) // false
, isType(Foo)(x => x) // false
, isType(Foo)(true) // false
, isType(Foo)(undefined) // false
, isType(Foo)(null) // false
);
console.log(
isType(Foo)(Foo(1)) // true
, isType(Foo)(Foo([])) // true
, isType(Foo)(Foo({})) // true
, isType(Foo)(Foo(x => x)) // true
, isType(Foo)(Foo(true)) // true
, isType(Foo)(Foo(undefined)) // false
, isType(Foo)(Foo(null)) // false
);
console.log(Foo(1) + Foo(2)); //3
用 typeOf <进行重构/ code>和
isType
。
如果(EVAL)
被应用,整个评估过程被调用。
If (EVAL)
is applied, the whole evaluation process is called.
因为它是一个幺半群,我将使用 M
不 L
。
Since it's a monoid, I will use M
not L
.
使用 JSON.stringfy验证一些帮助函数
成功,
Monoids
- 身份
- Associative
列表
- 累积
- 懒惰评估
规范分为每个简洁函数,它们的组成如下:
specifications are divided into every concise function, and the composition of them is the code below:
//Debug/validation use-----------------
const equalJSON = a => b => JSON.stringify(a) === JSON.stringify(b);
const logEq = a => b => {
const result = equalJSON(a)(b);
console.log(result);
return result;
}; //Debug/validation use-----------------
const isPrimitive = val => (val !== Object(val));
const toObj = p => !isPrimitive(p)
? p //object return
: (typeof (p) === "boolean")
? new Boolean(p)
: (typeof (p) === "number")
? new Number(p)
: (typeof (p) === "string")
? new String(p)
: p; //Symbol()
const selfAware = i => i[i] = i;
const isAware = i => (i[i] === i);
const I = i => (i === I) || (i == null)
? i
: selfAware(toObj(i));
const amI = i => (i === I)
? true
: (i == null)
? false
: isAware(i);
const flatArray = (arr1) => arr1
.reduce((acc, val) => Array.isArray(val)
? [...acc, ...flatArray(val)]
: [...acc, val], []);
const flatList = ls => ls.map(l => amI(l)
? flatList(l(EVAL)) : l);
//evaluation to be associative operation: flatten list
const evaluation = list => associative(list);
const associative = list => flatArray(flatList(list));
const identityType = f => { //left&right identity
const T = x => (x === T)
? T //left identity
: f(x);
return I(T); //right identity
};
const EVAL = Symbol();
const M = identityType( //Monoid type constructer
a => { // list accumulation recursion
const m = list => x => (x === EVAL)
? evaluation(list) // list() triggered to eval
: I(m([...list, x])); // data x joint
return m([])(a); //initial empty [] list and data a
}
);
//Validation================
console.log(
(M) //[Function: M]
);
console.log(
(M)(M)
);
console.log(
(M)(M)(M)
);
console.log(
(M)(M)(M)(M)
);
logEq(
(M)(M)
)(
(M)
); //true
logEq(
(M)(M)(M)
)(
(M)
); //true
logEq(
(M)(M)(M)(M)
)(
(M)
); //true
console.log(
(M)(EVAL) // []
);
console.log(
(M)(M)(EVAL) //[]
);
console.log(
(M)(M)(M)(EVAL) //[]
);
console.log(
(M)(M)(M)(M)(EVAL) //[]
);
const m = M(5);
//left identity
logEq(
(M)(m)
)(
(m)
); //true
//right identity
logEq(
(m)
)(
(m)(M)
); //true
console.log(
(M)(1)(2)(3) //{ [Function: n] isList: true }
);
logEq(
(M)(1)(2)(3)
)(
(M)(99)
); //true without evaluation
logEq(
(M)(1)(2)(3)(EVAL)
)(
(M)(99)(EVAL)
); //false with evaluation
console.log(
(M)(1)(2)(3)(EVAL) //[1, 2, 3]
);
console.log(
(M)(1)(M)(2)(3)(M)(EVAL) //[1, 2, 3]
);
logEq(
(M)(1)(2)(3)(EVAL) //[1,2,3]
)(
(M)(1)(M)(2)(3)(M)(EVAL) //[1,2,3]
); //true
console.log("associative----------------");
const a = (M)(1)(2)(3);
const b = (M)(4)(5)(6);
const c = (M)(99);
const ab = (a)(b);
const bc = (b)(c);
const abc1 = (ab)(c);
const abc2 = (a)(bc);
console.log("no eval yet----------------");
console.log(
(ab)(EVAL) //[1, 2, 3, 4, 5, 6]
);
console.log(
(bc)(EVAL) //[4, 5, 6, 99]
);
console.log(
(abc1)(EVAL) //[1, 2, 3, 4, 5, 6, 99]
);
console.log(
(abc2)(EVAL) //[1, 2, 3, 4, 5, 6, 99]
);
logEq(
(abc1)(EVAL)
)(
(abc2)(EVAL)
); // true for Associative law
这篇关于如何存储Monoidal List功能链的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!