Junkor

Applicative Functors

文章翻译自objc,原文连接:『Applicative Functors

在之前的『Currying』我们有这样一个用于登录验证的例子:

func login(email: String, pw: String, success: Bool -> ())

有可能经常碰到这种情况,作为可选的输入的参数,需要做一些必要的验证跟提示,例如:

if let email = getEmail() {
	if let pw = getPw() {
    	login(email, pw) { println("success: \($0)") }
	} else {
    	// error...
	}
} else {
	// error...
}

有一种更优雅的方式,就是使用applicative functors,其实swift中的optional类型就是applicative functors的一种实现(we can make use of the fact that optionals in Swift are an instance of applicative functors.),听起来有点费解,看例子。像applicative functors,例如optional类型,我们可以声明<*>操作符:

infix operator <*> { associativity left precedence 150 }
func <*><A, B>(lhs: (A -> B)?, rhs: A?) -> B? {
	if let lhs1 = lhs {
    	if let rhs1 = rhs {
        	return lhs1(rhs1)
    	}
}
	return nil
}

简而言之,如果操作符左右两侧元素都不为nil的话,该操作符作用于右侧的元素,并把它传递给左侧的函数。用这个操作符并配合我们之前讲过的『Currying』可以重写上边的例子:

if let f = curry(login) <*> getEmail() <*> getPw() {
	 f { println("success \($0)") }
} else {
	// error...
}

更漂亮简洁了,对吧?当然,刚开始看上去可能还是比较古怪,不过你可以多想想怎样把它应用到其他的场景。