我正在学习Scala中的函数式编程并阅读本书FPiS。
关于API设计(代数)的第131页,作者提到了以下内容:
正如我们在第7章中所讨论的,我们有兴趣了解什么 操作是原始的,什么操作是派生出来的 找到一组小而富有表现力的原语。一个好方法 探索用一组给定的基元来表达的东西就是选择 你想表达的一些具体例子,看看你是否可以 组装您想要的功能。当你这样做,寻找模式, 尝试将这些模式分解为组合器,并优化您的组合 原始人。我们鼓励您停止阅读并简单地玩 到目前为止我们写过的原语和组合子。如果你想 一些具体的例子来激励你,这里有一些想法:
他对表达原语的意思是什么?什么是原语?
(第7章根本没有解释原语。)
我正在成像,原始是可以使用组合器构建以获得更高级别的东西的最小的东西。
书中提出的问题:
如果我们可以在某个范围内生成单个
Int
,我们是否需要一个新的原语 在某个范围内生成(Int,Int)
对?
问题的答案是什么?
Int
是原始的吗?
什么是原始函数?
答案 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
上定义的操作unit
和Par
。
请特别注意最后一句,这是我上面没有强调的一点。您还应该阅读以下内容:7.3中有更多解释。
他对富有表现力的原语是什么意思?
原语不具有表现力,它是一组具有表现力的原语(包括组合子)。也就是说,它应该允许您不仅表达range
和pairInRange
,还表达您想要的所有其他生成器。
Int
是原始的吗?
没有。这是与“原始类型”(Int
,Double
等无关的“原始”的含义。)