Function 什么样的功能被视为;可组合的;?

Function 什么样的功能被视为;可组合的;?,function,scala,functional-programming,Function,Scala,Functional Programming,维基百科的文章说: 就像数学中常见的函数组合一样,每个函数的结果作为下一个函数的参数传递,最后一个函数的结果就是整个函数的结果 我有两个问题: 可组合函数必须同时具有参数和返回值 因此,以下功能不适用: def doNothing(): Unit = () def myName(): String = "My name" def eat(food:String): Unit = () 我的理解正确吗 这个功能会有副作用吗 def hello(name:String):String = {

维基百科的文章说:

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

我有两个问题:

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

    因此,以下功能不适用:

    def doNothing(): Unit = ()
    def myName(): String = "My name"
    def eat(food:String): Unit = ()
    
    我的理解正确吗

  • 这个功能会有副作用吗

    def hello(name:String):String = {
      println("name: " + name) // side-effect
      name + "!"
    }
    
    我们仍然认为它是“可组合的”吗? <p>2)如果函数有副作用,则不能认为它是函数

    1) 如果函数没有参数-它是一个常量。如果函数没有返回值-其返回值为
    单位
    (也可以是输入参数)

    另外,你也可以为“脏”函数定义一个“函数”(子程序)组合,但这不是人们通常所说的意思;正如数学中的函数合成一样,它意味着纯函数的合成


    谈论Scala:

    scala> def doNothing(): Unit = ()
    doNothing: ()Unit
    
    scala> (doNothing _)
    res0: () => Unit = <function0>
    
    scala> (doNothing _) andThen (doNothing _)
    <console>:9: error: value andThen is not a member of () => Unit
                  (doNothing _) andThen (doNothing _)
                                ^
    
    scala> def doSomething(a: Int) = a
    doSomething: (a: Int)Int
    
    scala> (doSomething _) andThen (doSomething _)
    res2: Int => Int = <function1>
    

    数学的形式语言和编程的口语语言的混合使得这些对话变得困难。您在这里处理的是两个上下文加载的单词:“composable”和“function”

    数学中的函数合成 “函数”的数学概念→ B是从某个集合a到某个集合B的映射,“函数组合”是由
    。对于某些
    f:A→ B
    g:B→ C
    g∘f
    是一个函数
    a→ C
    ,使
    (g∘f) (x)=g(f(x))用于
    A
    中的所有
    x
    。如果任何两个函数的域/辅域以这种方式匹配(换句话说,这样的一对函数“可以组合”),则该组合被定义为任意两个函数,我们通过声明“函数是可组合的”来描述这一点

    编程中的可组合性 作为一个定性术语,我们经常在软件中使用“可组合性”来描述一组组合的能力,这些组合可以通过组合小的组合来构建大的东西。从这个意义上讲,程序员将函数(作为一个整体)描述为“非常可组合”,因为函数可以(并且,在Haskell这样的纯函数语言中,函数可以)构成整个程序的大小部分

    在软件中,我们还看到“可组合”一词的用法更加人性化,它往往与“模块化”有关。当组件是无状态的,关注点是分离的,并且API具有较低的表面积时,编写程序更容易而不会出错。我们称赞这种设计的组件是“可组合的”——不仅因为它们可以组合,还因为它们易于正确组合

    函数在程序设计中的应用 我将使用稍微过时的术语“子程序”,因为我不知道用我们这个时代的说法来讨论这个问题的好方法。如果子例程不执行任何IO(并且总是停止,不抛出…),那么它实现(或“是”)数学意义上的“函数”。IO子例程表面上与函数相似,因为它们可能有输入和输出值,但相似性仅限于此。我们第一次讨论的关于“函数组合”的对话都不适用

    这是我们遇到的最棘手的语言难题,因为“函数”一词已成为任何子程序的常用词,即使是执行IO的子程序。FP爱好者倾向于与之抗争——人们说“如果它有IO,它就不是一个功能”——但这场流行之战已经失败,现在已经没有回头路了。在大多数编程环境中,所有子例程都称为“函数”,区分满足数学定义的函数的唯一方法是将它们称为“纯函数”


    根据这些定义,让我们来回答您的问题:

    “可组合函数必须同时具有参数和返回值?” 关于这个问题,有一些无聊的事情需要指出。首先,Scala中的每个函数在技术上都有一个返回类型。如果该类型是
    Unit
    ,为简洁起见,可以省略它,但它仍然是返回类型

    一个空值(0-arg)函数可以简单地转换成一个带参数的等价函数。所以说真的,没关系。如果您需要用参数组合函数,而
    f
    没有参数,那么您可以只编写
    \uu=>f

    “这个功能会有副作用吗?” 只是语义上的争论。在Scala的上下文中,最恰当的说法是它是一个
    函数
    (或者在技术上是一个“方法”,取决于它的定义),但由于副作用,它不是一个纯函数

    “我们仍然认为这是“合乎情理的”吗? 有点。所有这些东西仍然以一种相当普遍的方式“结合在一起”,所以是的,它们确实是在软件意义上组合的。虽然纯函数比不纯函数组成得更好。函数组合的数学概念不适用于非纯函数的子程序

    最后,如果您想知道它们是否真的在Scala中使用
    compose
    方法进行组合,则不需要堆栈溢出;只要问问编译器。

    你认为我在问题中定义的“函数”中没有一个是不可组合的吗?或者其中一些是?
    scala> def eat(food:String): Unit = ()
    eat: (food: String)Unit
    
    scala> (eat _) andThen (doNothing _)
    <console>:10: error: type mismatch;
     found   : () => Unit
     required: Unit => ?
                  (eat _) andThen (doNothing _)
                                   ^
    
    scala> def doNothingU(u: Unit): Unit = ()
    doNothingU: (u: Unit)Unit
    
    scala> (doNothingU _) andThen (doNothingU _)
    res5: Unit => Unit = <function1>
    
    scala> (eat _) andThen (doNothingU _)
    res6: String => Unit = <function1>
    
    scala> (doNothingU _) compose eat
    res11: String => Unit = <function1>