Como armazenar dados de uma cadeia funcional da Lista Monoidal?
Este é um tópico avançado da minha pergunta anterior aqui:
Como armazenar dados de uma cadeia funcional?
A breve ideia é
Uma função simples abaixo:
const L = a => L;
formulários
L
L(1)
L(1)(2)
...
Isso parece formar uma lista, mas os dados reais não são armazenados, portanto, se for necessário armazenar dados como [1,2], qual é a prática mais inteligente para executar a tarefa?
Uma das idéias de destaque é de @ user633183, que marquei como resposta aceita (consulte o link da pergunta), e outra versão da função ao curry também é fornecida pelo @ Matías Fidemraizer.
Então aqui vai:
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())
O que eu realmente gosto é a avaliação preguiçosa.
Embora a abordagem fornecida satisfaça o que mencionei, essa função perdeu a estrutura externa ou devo mencionar:
Estrutura algébrica const L = a => L;
lista de formulários e, mais fundamentalmente, nos fornece umaestrutura algébrica doelemento de identidade, potencialmente junto comMonoid ouMagma.
Deixou uma identidade à direitaUm dos exemplos mais fáceis de Monoids e identidade é o número e"Strings"
e[Array]
em JavaScript.
0 + a === a === a + 0
1 * a === a === a * 1
Em Strings, o quoate vazio""
é o elemento de identidade.
"" + "Hello world" === "Hello world" === "Hello world" + ""
O mesmo vale para[Array]
.
O mesmo vale paraL
:
(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
);
e a óbvia imutabilidade de identidade:
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
);
Também o abaixo:
const L = a => L;
const a = (L)(1)(2)(3);
const b = (L)(1)(L)(2)(3)(L);
console.log(
(a) === (b) //true
);
QuestõesQual é a maneira mais inteligente ou elegante (muito funcional e sem mutações (semArray.push
, também)) para implementarL
que satisfaça três requisitos:
Uma função simples:
const L = a => L;
já satisfaz a lei de identidade como já vimos.
Requisito 1 - método eval ()ApesarL
satisfaça a lei de identidade, não há método para acessar os dados listados / acumulados.
(As respostas fornecidas na minha pergunta anterior fornecem a capacidade de acumulação de dados, mas infringem a lei de identidade.)
A avaliação preguiçosa parece a abordagem correta, fornecendo uma especificação mais clara:
providenciareval
método deL
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]
);
Requisito 3 - Direito associativo monóideAlém da proeminente estrutura Identify, o Monoids também satisfazDireito associativo
(a * b) * c === a * b * c === a * (b * c)
Isso significa simplesmente "achatar a lista"; em outras palavras, a estrutura não contém listas aninhadas.
[a, [b, c]]
não é bom.
Amostra:
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]
);
Isso é tudo para 3 requisitos para implementarL
como um monóide.
Esse é um grande desafio para a programação funcional para mim e, na verdade, tentei por um tempo, mas, fazendo as perguntas anteriores, é uma prática muito boa compartilhar meu próprio desafio, ouvir as pessoas e ler seu código elegante.
Obrigado.