为什么我需要一个新的原语?

时间:2017-05-24 12:38:19

标签: scala functional-programming

我正在学习Scala中的函数式编程并阅读本书FPiS

关于API设计(代数)的第131页,作者提到了以下内容:

  

正如我们在第7章中所讨论的,我们有兴趣了解什么   操作是原始的,什么操作是派生出来的   找到一组小而富有表现力的原语。一个好方法   探索用一组给定的基元来表达的东西就是选择   你想表达的一些具体例子,看看你是否可以   组装您想要的功能。当你这样做,寻找模式,   尝试将这些模式分解为组合器,并优化您的组合   原始人。我们鼓励您停止阅读并简单地玩   到目前为止我们写过的原语和组合子。如果你想   一些具体的例子来激励你,这里有一些想法:

他对表达原语的意思是什么?什么是原语
(第7章根本没有解释原语。)

我正在成像,原始是可以使用组合器构建以获得更高级别的东西的最小的东西。

书中提出的问题:

  

如果我们可以在某个范围内生成单个Int,我们是否需要一个新的原语   在某个范围内生成(Int,Int)对?

问题的答案是什么?
Int是原始的吗? 什么是原始函数?

1 个答案:

答案 0 :(得分:3)

  

什么是原始人?

     

我正在成像,原始是可以使用组合器构建以获得更高级别的东西的最小的东西。

右。所以在这种情况下:您正在开发一个API,其类型Gen[A]表示“类型为A的值的生成器”。此API中的组合器将是在Gen上运行并生成Gen的方法。但是,您还需要一些东西来应用这些组合器:生成Gen而不从一个开始的方法。

其中一个可能是range(min: Int, max: Int): Gen[Int]。如果您现在需要pairInRange(min: Int, max: Int): Gen[(Int, Int)],是否需要以实现range的方式实现它,或者您可以使用组合器从range构建它吗?如果可以的话,你需要什么组合器?在这种情况下,你应该得出结论

def pairInRange(min: Int, max: Int) = pair(range(min, max), range(min, max))

是一个合理的实现,假设有一个pair组合子(想想它的类型应该是什么),所以pairInRange不需要是一个原语:它是一个派生的操作。原始操作是那些未派生的操作。

您同样可以pairInRange作为原始,def pair(min: Int, max: Int) = pairInRange(min, max).map(_._1)作为派生;这只是一种不自然的设计方式!

  

(第7章根本没有解释原语。)

现在我已经回到家并可以访问这本书了:是的,确实如此。如果你在书中搜索“原始”(假设你有电子版),你会在7.1.3显式分叉中找到这个引用:

  
    

函数lazyUnit派生组合子的简单示例,而不是     原始组合器,如unit。我们只能根据其他方式定义lazyUnit     操作。之后,当我们选择Par的代表时,lazyUnit将不需要     知道关于这种表示的任何事情 - 它对Par的唯一了解就是通过     fork上定义的操作unitPar

  

请特别注意最后一句,这是我上面没有强调的一点。您还应该阅读以下内容:7.3中有更多解释。

  

他对富有表现力的原语是什么意思?

原语不具有表现力,它是一组具有表现力的原语(包括组合子)。也就是说,它应该允许您不仅表达rangepairInRange,还表达您想要的所有其他生成器。

  

Int是原始的吗?

没有。这是与“原始类型”(IntDouble等无关的“原始”的含义。)