por que folktale e ramda são tão diferentes?

96

Estou aprendendo javascript FP lendo o livro do DrBoolean .

Procurei por uma biblioteca de programação funcional. Encontrei Ramda e Folktale. Ambos afirmam ser uma biblioteca de programação funcional.

Mas eles são tão diferentes:

  • Ramda parece conter funções utilitárias para lidar com lista: mapear, reduzir, filtrar e funções puras: curry, compor. Não contém nada para lidar com mônada, functor.

  • Folktale, entretanto, não contém nenhum utilitário para listas ou funções. Parece implementar algumas estruturas algébricas em javascript, como monad: Maybe, Task ...

Na verdade, encontrei mais bibliotecas, todas parecem se enquadrar em duas categorias. O sublinhado e o lodash são como Ramda. A terra da fantasia, a fantasia pontual são como contos populares.

Essas bibliotecas muito diferentes podem ser chamadas de funcionais e, em caso afirmativo, o que torna cada uma delas uma biblioteca funcional?

Aaron Shen
fonte
1
use o que se adapta às suas necessidades e estilo e está bem documentado
charlietfl
1
Descobri que há realmente três significados comuns para "programação funcional", especialmente em JS. 1. usando funções puras de ordem superior em conjuntos como arrays., Ex [1,2,3].map(fnSquare).reduce(fnSum)2. estruturas do tipo Y-combinator amplamente acadêmicas do tipo "look ma no var ". 3. usando Function.prototypepara modificar o comportamento de outras funções, comovar isMissingID=fnContains.partial("id").negate();
dandavis
10
Um autor de Ramda aqui: Ramda é uma biblioteca de utilitários de baixo nível. Pretende-se tornar um certo estilo funcional mais simples em JS, especialmente trabalhando com funções de composição. Ramda funciona bem com a especificação FantasyLand, incluindo implementações dela, como Folktale. Essas bibliotecas são projetadas para um propósito um pouco diferente. Eles são construídos em torno do reconhecimento de tipos de dados abstratos comuns e permitindo acesso consistente a eles: coisas como Monoids, Functors e Monads. Ramda vai trabalhar com eles e tem um projeto paralelo para criar alguns, mas é, como você diz, um foco muito diferente.
Scott Sauyet,
1
@KeithNicholas: Sim, há um Gitter Room
Scott Sauyet
2
Dê uma olhada no Santuário também - github.com/plaid/sanctuary . Ele é baseado em ramda, mas também abrange os tipos de terra da fantasia.
arcseldon

Respostas:

180

Características Funcionais

Não existe um limite bem definido do que define a programação funcional ou uma biblioteca funcional. Alguns recursos das linguagens funcionais são integrados ao Javascript:

  • Funções de primeira classe e ordem superior
  • Lambdas / funções anônimas, com fechamentos

Outros são possíveis de realizar em Javascript com algum cuidado:

  • Imutabilidade
  • Transparência Referencial

Outros ainda fazem parte do ES6 e estão parcial ou totalmente disponíveis agora:

  • Funções compactas e até concisas
  • Desempenho de recursão por meio de otimização de chamada final

E há muitos outros que estão realmente além do alcance normal do Javascript:

  • Correspondência de padrões
  • Avaliação preguiçosa
  • Homoiconicidade

Uma biblioteca, então, pode escolher quais tipos de recursos ela está tentando suportar e ainda ser razoavelmente chamada de "funcional".

Especificação da terra da fantasia

Fantasy-terra é uma especificação para um número de tipos padrão portados de Categoria matemática Teoria e Abstract Algebra a programação funcional, tipos, tais como Monoid , Functor e Mônada . Esses tipos são bastante abstratos e estendem noções possivelmente mais familiares. Functors, por exemplo, são containers que podem ser transmitidos mapcom uma função, da mesma forma que um array pode ser transmitido mapusando Array.prototype.map.

Conto popular

Folktale é uma coleção de tipos que implementam várias partes da especificação Fantasy-land e uma pequena coleção de funções utilitárias associadas. Esses tipos são coisas como Maybe , Either , Task (muito semelhante ao que em outro lugar é chamado de Futuro e um primo mais legítimo de uma promessa) e Validação

Folktale é talvez a implementação mais conhecida da especificação Fantasy-land, e é muito respeitada. Mas não existe uma implementação definitiva ou padrão; fantasy-land apenas especifica tipos abstratos, e uma implementação, é claro, deve criar tais tipos concretos. A afirmação da Folktale de ser uma biblioteca funcional é clara: ela fornece tipos de dados encontrados normalmente em linguagens de programação funcionais, os que o tornam substancialmente mais fácil de programar de maneira funcional.

Este exemplo, da documentação do Folktale ( observação : não nas versões recentes dos documentos), mostra como ele pode ser usado:

// We load the library by "require"-ing it
var Maybe = require('data.maybe')

// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
  return xs.reduce(function(result, x) {
    return result.orElse(function() {
      return predicate(x)?    Maybe.Just(x)
      :      /* otherwise */  Maybe.Nothing()
    })
  }, Maybe.Nothing())
}

var numbers = [1, 2, 3, 4, 5]

var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)

var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing

Ramda

Ramda (isenção de responsabilidade: eu sou um dos autores) é um tipo de biblioteca muito diferente. Não fornece novos tipos para você. 1 Em vez disso, ele fornece funções para facilitar a operação em tipos existentes. É construído em torno das noções de compor funções menores em funções maiores, de trabalhar com dados imutáveis, de evitar efeitos colaterais.

Ramda opera especialmente em listas, mas também em objetos e, às vezes, em Strings. Ele também delega muitas de suas chamadas de tal maneira que irá interoperar com Folktale ou outras implementações de Fantasy-land. Por exemplo, a mapfunção de Ramda opera de forma semelhante àquela de Array.prototype, portanto R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]. Mas como o Folktale Maybeimplementa a Functorespecificação Fantasy-land , que também especifica o mapa, você também pode usar Ramda mapcom ele:

R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing

A afirmação de Ramda de ser uma biblioteca funcional consiste em facilitar a composição de funções, nunca alterando seus dados e apresentando apenas funções puras. O uso típico de Ramda seria construir funções mais complexas, compondo outras menores, como visto em um artigo sobre a filosofia de Ramda

// :: [Comment] -> [Number]  
var userRatingForComments = R.pipe(
    R.pluck('username')      // [Comment] -> [String]
    R.map(R.propOf(users)),  // [String] -> [User]
    R.pluck('rating'),       // [User] -> [Number]
);

Outras Bibliotecas

Na verdade, encontrei mais bibliotecas, todas parecem se enquadrar nas duas categorias. sublinhado, lodash são muito parecidos com Ramda. A terra da fantasia, a fantasia pontual são como contos populares.

Isso não é muito preciso. Em primeiro lugar, Fantasy-land é simplesmente uma especificação que as bibliotecas podem decidir implementar para vários tipos. Folktale é uma das muitas implementações dessa especificação, provavelmente a mais completa, certamente uma das mais maduras. A fantasia sem pontos e a fantasia ramda são outras, e existem muitas mais .

O sublinhado e o lodash são superficialmente como Ramda no sentido de que são bibliotecas improvisadas, fornecendo um grande número de funções com muito menos coesão do que algo como Folktale. E mesmo a funcionalidade específica muitas vezes se sobrepõe à de Ramda. Mas em um nível mais profundo, Ramda tem preocupações muito diferentes dessas bibliotecas. Primos mais próximos de Ramda são provavelmente bibliotecas como FKit , Fnuc e Wu.js .

Bilby está em uma categoria própria, fornecendo várias ferramentas, como as fornecidas por Ramda, e alguns tipos consistentes com Fantasy-land. (O autor de Bilby é o autor original de Fantasy-land também.)

Sua chamada

Todas essas bibliotecas têm o direito de ser chamadas de funcionais, embora variem muito na abordagem funcional e no grau de comprometimento funcional.

Algumas dessas bibliotecas funcionam bem juntas. Ramda deve funcionar bem com Folktale ou outras implementações de Fantasy-land. Como suas preocupações quase não se sobrepõem, eles realmente não entram em conflito, mas Ramda faz apenas o suficiente para tornar a interoperação relativamente tranquila. Isso provavelmente é menos verdadeiro para algumas das outras combinações que você pode escolher, mas a sintaxe de função mais simples do ES6 também pode aliviar um pouco a dor da integração.

A escolha da biblioteca, ou mesmo o estilo de biblioteca a ser usado, vai depender do seu projeto e das suas preferências. Existem muitas boas opções disponíveis, e os números estão crescendo, e muitas delas estão melhorando muito. É um bom momento para fazer programação funcional em JS.


1 Bem, há um projeto paralelo, fantasia ramda fazendo algo semelhante ao que o Folktale faz, mas não faz parte da biblioteca central.

Scott Sauyet
fonte
1
Seria justo dizer que o ES6 tem a capacidade de avaliação preguiçosa com a introdução do Yield? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Marcel Lamothe
8
Não. yieldTorna mais fácil fazer o tipo de processamento de lista preguiçoso feito por Lazyou lz.js. Mas isso não ajuda com a preguiça de nível de linguagem. someFunc(a + b)em JS primeiro adiciona os valores de ae bentão fornece esse resultado como o parâmetro para someFunc. O equivalente em Haskell não faz isso. Se a função chamada nunca usar esse valor, ela nunca realizará a adição. Se eventualmente usá-lo, é considerado uma expressão a ser calculada até que seu resultado seja necessário. Se você nunca fizer nada que o force (como IO), ele nunca executará o cálculo.
Scott Sauyet
@ScottSauyet talvez você possa argumentar que "avaliação preguiçosa" de alguma forma está disponível por meio de geradores ES6, por exemplo - muitos frameworks JS têm características de "preguiça" - RxJs, ImmutableJs etc.
arcseldon
8
Esta resposta deve ser um capítulo ou seção do livro de DrBoolean. :)
Set
1
A documentação do Ramda tende a usar "lista" como um atalho para a coisa mais próxima que o JS oferece às listas, arrays densos. Eles têm características de desempenho diferentes das listas puras e, claro, uma API um pouco diferente, mas podem ser usados ​​para os mesmos fins e são o tipo nativo mais próximo (mas consulte github.com/funkia/list ) disponível para Ramda's API, que conceitualmente deseja trabalhar com listas puras. Eu argumentaria que os arrays não são verdadeiros, já que os arrays de estilo C não são mais canônicos do que os JS, e nenhum realmente próximo aos matemáticos, mas esse é um ponto secundário.
Scott Sauyet