关于使用Swiftz库的问题(函数式编程)

About using Swiftz library issues(Functional programing)

最近在用swift编程语言学习函数式编程,发现了一个库,名字叫Swiftz,发现了一个很奇怪的函数调用方式,想问问有没有人知道为什么成功了,谢谢!

这里的代码很简单,Person().walk <*> 10对我来说太连线了,<*>之前和<*>之后都是空格,但没有发生错误。

import Swiftz

class Person {
    func walk(step: Int) {
        print("walk \(step) step")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        Person().walk <*> 10
        // ⬇️ normal way for same result
        // Person().walk(step: 10)
    }
}

// print result: walk 10 step

我试图在 Swiftz 中找到 <*> 代码,但原因不明。

public func <*> <A, B>(f : ((A) -> B)?, a : A?) -> B? {
    return f.flatMap { [=11=] <^> a }
}

<*> 是此库中定义的运算符。

表示运算符定义有两种类型作为参数,记为A和B。

运算符有两个参数 f 和 a 用于左侧和右侧。在您的示例中,f 是 Person().walk,a 是 10。它 return 是一个可选的 B,其中 B 是 Person.walk 将 return 如果您调用它的类型.

f 是一个可选函数,以 A 作为参数并 returning B。在你的例子中,walk 接受一个 Int 参数和 returns Void,所以 A 是 Int,B 是 Void .右边应该是 A?,这很好,因为 10 是 Int 类型。

然后它会调用您需要检查的另一个运算符。重要的是:该运算符在左侧接受任何函数,该函数具有一个 A 类型的参数,在右侧接受一个类型为 A? 的值,并且 returns 无论该函数将具有 returned.

Person().walk 是一个函数 - (Int) -> Void10 是一个 Int<*> 所做的是 function application - 它将左操作数应用于作为右操作数的函数。换句话说,它以左边的东西作为参数调用右边的函数。只是函数及其参数都可以是可选的(注意签名中的 ?s)。这有点像 Haskell 的 <*>,但专门针对 MaybeOptional 的 Haskell 对应)。

如果删除所有可选处理:

public func <*> <A, B>(f : ((A) -> B), a : A) -> B {
    return f(a)
}

是的,这就是它的作用(加上处理可选项)!

可选的处理方式也不难理解。 [=20=] <^> a 就意味着 a.map([=21=])。两者 flatMap。这些是内置的 Swift 函数。如果您不了解它们的工作原理,请阅读 。最终它所做的是,如果 fa 为零,则 <*> returns 也为零。

现在您可能想知道为什么我们需要这个功能。好吧,让“应用这个函数”本身成为一个函数意味着我们可以将它传递给其他函数,将它与其他函数组合起来!

但是,我认为这在 Swift 中的效果不如在 Haskell 中的效果。在 Swift 中,编译器需要能够将每个类型参数推断为已知类型,这会使许多在 Haskell 中可以轻松完成的事情变得困难和繁琐。