什么样的功能被认为是"可组合的"?

Fre*_*ind 4 functional-programming scala function

维基百科文章功能组成(计算机科学)说:

就像数学中常用的函数组合一样,每个函数的结果都作为下一个函数的参数传递,最后一个函数的结果是整体的结果.

我有两个问题:

  1. 可组合函数必须同时包含参数和返回值?

    所以以下功能不是:

    def doNothing(): Unit = ()
    def myName(): String = "My name"
    def eat(food:String): Unit = ()
    
    Run Code Online (Sandbox Code Playgroud)

    我的理解是否正确?

  2. 这个功能可以副作用吗?

    def hello(name:String):String = {
      println("name: " + name) // side-effect
      name + "!"
    }
    
    Run Code Online (Sandbox Code Playgroud)

    我们还认为它是"可组合的"吗?

Chr*_*tin 7

数学形式语言与编程中更多口语的混合使得这些对话变得困难.你在这里处理两个上下文加载的单词:"composable"和"function".

功能构成 - 在数学中

"函数"的数学概念A ? B是从某个集合A到某个集合B的映射,"函数组合"是由表示的特定操作?.对于一些f: A ? Bg: B ? C,f?g是一个函数A ? C,使得(f?g)(x) = f(g(x))对所有xA.如果它们的域/ codomain以这种方式匹配(换句话说,这样的一对函数"可以组合"),则为任何两个函数定义该组合,并且我们通过声明"函数是可组合的"来描述它.

可组合性 - 编程

作为一个定性术语,我们经常在软件中使用"可组合性"来描述一组组合物通过组合小组合物来构建大型事物的能力.从这个意义上讲,程序员将函数(作为一个整体)描述为"非常可组合",因为函数可以(以及像Haskell这样的纯函数式语言)构成整个程序的大小.

在软件中,我们还看到了一种更加以人为本的术语"可组合"的用法,这种用法往往与"模块化"有关.当组件处于无状态时,关注点被分离,并且API具有较低的表面积,更容易编写程序而不会出错.我们赞扬这种设计的组件是"可组合的" - 不仅仅因为它们可以组合在一起,而且因为它们很容易正确组合.

功能 - 编程

我将使用稍微过时的术语"子程序",因为我不知道用我们这个时代的说法讨论这个问题的好方法.如果一个子程序没有做任何IO(并且总是停止,并且不会抛出......),那么它在数学意义上实现(或"是")一个"函数".IO子程序与函数表面相似,因为它们可能具有输入和输出值,但相似性在那里停止.我们首先讨论的关于"功能组成"的谈话都不适用.

这就是我们遇到最棘手的语言难度的地方,因为"函数"这个词已经成为常用的指代任何子程序,甚至是执行IO的子程序.FP爱好者倾向于打击这个 - 人们说"如果它做了IO,它不是一个功能" - 但是这种人气之战已经失去了,现在没有回头路了.在大多数编程上下文中,所有子例程都称为"函数",区分满足数学定义的函数的唯一方法是将它们称为"纯函数".


考虑到这一背景,我恭敬地声称你的问题相当无趣,如果我们要从这次讨论中获得任何价值,他们需要额外的动力和背景.

"可组合函数必须同时具有参数和返回值?"

关于这个问题,有一些无聊的事情需要指出.首先,Scala中的每个函数在技术上都具有返回类型.如果是这种类型Unit,可能会因为简洁而省略,但它仍然是返回类型.

并且一个nullary(0-arg)函数可以通过参数简单地转换为等价函数.真的,这没关系.如果您需要使用参数组合函数并且f没有参数,则可以编写_ => f.

"这个功能有副作用吗?"

仅仅是一种语义争吵.在Scala的上下文中,最恰当的说法是它Function(或者在技术上可能是"方法",取决于它的定义位置),但由于副作用,它不是纯函数.

"我们仍然认为它'可以组合'吗?"

有点.所有这些东西仍然以相当普遍的方式"聚集在一起",所以是的,它们确实在软件意义上构成.虽然纯函数比不纯函数更好.函数组合的数学概念不适用于非纯函数的子程序.

最后,如果你想知道它们是否在Scala中使用compose方法编写Function1,你就不需要Stack Overflow; 只要问编译器.