简体   繁体   English

Ramda 与 FP 类型

[英]Ramda with FP Types

Recently I have decided to switch from lodash to ramda to play with functional way of composing my logic.最近我决定从 lodash 切换到 ramda,以使用功能方式来编写我的逻辑。 I love it!我喜欢它! After some extensive digging into FP I have found that's it's not only about handy pure/point free utilities (ramda), but more about complex (at least for me) math abstractions (fantasy-land).在对 FP 进行了一些广泛的挖掘之后,我发现它不仅与方便的纯/无点实用程序 (ramda) 有关,而且更多地与复杂的(至少对我而言)数学抽象(fantasy-land)有关。 I don't get all of it, but Either and Task pattern looks very handy.我没有全部了解,但Either 和Task 模式看起来非常方便。 Problem is that I am not sure how to merge it with ramda utilities.问题是我不确定如何将它与 ramda 实用程序合并。 I know about ramda-fantasy, but it's no longer maintained.我知道 ramda-fantasy,但它不再维护。 Ramda-fantasy suggested libraries doesn't work the same way as ramda-fantasy. Ramda-fantasy 建议的库与 ramda-fantasy 的工作方式不同。 With all this new information about Monads/Monoids/Functors types I am completely lost.有了关于 Monads/Monoids/Functors 类型的所有这些新信息,我完全迷失了。

For example, what the convention for this?例如,这个约定是什么?

Right('boo')
  .map(x => x + '!')
  .map(x => x.toUpperCase())

vs 

R.pipe(
  R.map(x => x + '!')
  R.map(x => x.toUpperCase())
)(Right('boo'))

Am I don't need ramda If I will decide to switch to Monads all the way?如果我决定一直切换到 Monads,我是否不需要 ramda?

One way to think about it is to think about types versus functions.考虑它的一种方法是考虑类型与函数。

Ramda offers a large collection of utility functions. Ramda 提供了大量实用函数。 They operate on arrays, on objects, on functions, on strings, on numbers, etc. But they also operate on user-defined types.它们对数组、对象、函数、字符串、数字等进行操作。但它们也对用户定义的类型进行操作。 So in your example, R.map operates on anything which matches the Functor specification .因此,在您的示例中, R.map对与Functor 规范匹配的任何内容进行操作。 If the implementation of Either you use matches that specification, then Ramda's map will operate on it.如果您使用的Either一实现与该规范匹配,则 Ramda 的map将对其进行操作。

But Ramda does not supply types .但是 Ramda 不提供类型 It works with the built-in types such as Object, Array, Function, etc. But -- arguably outside Lens -- it does not supply any types of its own.它适用于内置类型,例如 Object、Array、Function 等。但是——可以说是在Lens之外——它不提供任何自己的类型。 Libraries such as Folktale provide large collections of types, such as Maybe , Result , Validation , Task and Future ; Folktale 等库提供了大量类型的集合,例如MaybeResultValidationTaskFuture more dedicated ones such as Fluture provide powerful versions of one specific type ( Future ).更专业的,例如 Fluture 提供了一种特定类型( Future )的强大版本。 All of these types implement the Functor specification.所有这些类型都实现了 Functor 规范。 A very incomplete list of such implementations is supplied by FantasyLand . FantasyLand 提供了一个非常不完整的此类实现列表。

These two notions, functions on an abstract type and collections of types are complementary.这两个概念,抽象类型上的函数和类型集合是互补的。 A Ramda function which works on any functor will work on whatever version of Either you use (so long as it matches the specification.) More on this relationship is in this StackOverflow Q+A .适用于任何函子的 Ramda 函数将适用于您使用的任何版本的任一版本(只要它符合规范。)有关此关系的更多信息在此StackOverflow Q+A 中

The question compared these two snippets:这个问题比较了这两个片段:

Right('boo')
  .map(x => x + '!')
  .map(x => x.toUpperCase())

and

R.pipe(
  R.map(x => x + '!')
  R.map(x => x.toUpperCase())
)(Right('boo'))

But neither is how I would think of the problem from a Ramda perspective.但我也不会从 Ramda 的角度思考这个问题。 Ramda is all about functions . Ramda 是关于函数的 It supplies functions and expects you to use them to build more sophisticated functions, and then to use those to build even higher level functions.它提供函数并期望您使用它们构建更复杂的函数,然后使用它们构建更高级别的函数。

If we wrote this function:如果我们写了这个函数:

const bigBang = pipe(
  map (x => x + '!'),
  map (x => x .toUpperCase ())
)

or perhaps this version或者这个版本

const bigBang = pipe (
  map (concat (__, '!')),
  map (toUpper)
)

Then this function is now available to use on many types.然后此功能现在可用于许多类型。 For example:例如:

bigBang (['boo', 'scared', 'you'])     //=> ['BOO!', 'SCARED!', 'YOU!']
bigBang ({a: 'boo', b: 'ya'})          //=> {a: 'BOO!', b: 'YA!}
bigBang ((s) => s .repeat (2)) ('boo') //=> 'BOOBOO!'
bigBang (Right ('boo'))                //=> Right ('BOO!') 
bigBang (Left ('oops'))                //=> Left ('oops') 
bigBang (Just ('boo'))                 //=> Just ('BOO!') 
bigBang (Nothing())                    //=> Nothing ()
bigBang (Future ('boo'))               //=> Future ('BOO!')

The first three -- Array, Object, and Function implementations -- are supplied by Ramda.前三个——数组、对象和函数实现——由 Ramda 提供。 But the others still work since Ramda interoperates with the FantasyLand Functor specification.但是由于 Ramda 与 FantasyLand Functor 规范互操作,其他的仍然有效。 And it will work if you supply your own map method on your type (or even better a fantasy-land/map method.)如果您在您的类型上提供自己的map方法(或者甚至更好的fantasy-land/map方法),它将起作用。

So no, you don't need Ramda to work with Monads or with other abstract types.所以不,你不需要 Ramda 来处理 Monads 或其他抽象类型。 You can work directly with their implementation.您可以直接使用它们的实现。 But Ramda offers some nice ways to interoperate with them in a generic manner.但是 Ramda 提供了一些很好的方式来以通用的方式与它们进行互操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM