关于使用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 }
}
<*> 是此库中定义的运算符。
运算符有两个参数 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) -> Void
,10
是一个 Int
。 <*>
所做的是 function application - 它将左操作数应用于作为右操作数的函数。换句话说,它以左边的东西作为参数调用右边的函数。只是函数及其参数都可以是可选的(注意签名中的 ?
s)。这有点像 Haskell 的 <*>
,但专门针对 Maybe
(Optional
的 Haskell 对应)。
如果删除所有可选处理:
public func <*> <A, B>(f : ((A) -> B), a : A) -> B {
return f(a)
}
是的,这就是它的作用(加上处理可选项)!
可选的处理方式也不难理解。 [=20=] <^> a
就意味着 a.map([=21=])
。两者 flatMap
。这些是内置的 Swift 函数。如果您不了解它们的工作原理,请阅读 。最终它所做的是,如果 f
或 a
为零,则 <*>
returns 也为零。
现在您可能想知道为什么我们需要这个功能。好吧,让“应用这个函数”本身成为一个函数意味着我们可以将它传递给其他函数,将它与其他函数组合起来!
但是,我认为这在 Swift 中的效果不如在 Haskell 中的效果。在 Swift 中,编译器需要能够将每个类型参数推断为已知类型,这会使许多在 Haskell 中可以轻松完成的事情变得困难和繁琐。
最近在用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 }
}
<*> 是此库中定义的运算符。
运算符有两个参数 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) -> Void
,10
是一个 Int
。 <*>
所做的是 function application - 它将左操作数应用于作为右操作数的函数。换句话说,它以左边的东西作为参数调用右边的函数。只是函数及其参数都可以是可选的(注意签名中的 ?
s)。这有点像 Haskell 的 <*>
,但专门针对 Maybe
(Optional
的 Haskell 对应)。
如果删除所有可选处理:
public func <*> <A, B>(f : ((A) -> B), a : A) -> B {
return f(a)
}
是的,这就是它的作用(加上处理可选项)!
可选的处理方式也不难理解。 [=20=] <^> a
就意味着 a.map([=21=])
。两者 flatMap
。这些是内置的 Swift 函数。如果您不了解它们的工作原理,请阅读 f
或 a
为零,则 <*>
returns 也为零。
现在您可能想知道为什么我们需要这个功能。好吧,让“应用这个函数”本身成为一个函数意味着我们可以将它传递给其他函数,将它与其他函数组合起来!
但是,我认为这在 Swift 中的效果不如在 Haskell 中的效果。在 Swift 中,编译器需要能够将每个类型参数推断为已知类型,这会使许多在 Haskell 中可以轻松完成的事情变得困难和繁琐。