Curried中缀运营商在swift中.可能吗?

mus*_*afa 4 operator-overloading currying swift

我正在尝试实现功能组合.起初我定义了一个名为的函数compose.

func compose<A,B,C>(f:(B -> C))(g: (A -> B)) -> A -> C {
    return { f(g($0)) }
}
Run Code Online (Sandbox Code Playgroud)

这非常有效.例如,如果我有notisEven功能像

func not(value: Bool) -> Bool {
    return !value
}

func even(value: Int) -> Bool {
    return value % 2 == 0
}
Run Code Online (Sandbox Code Playgroud)

odd功能可以来定义noteven这样的:

func odd(value: Int) -> Bool {
    return compose(not)(isEven)(value)
}
Run Code Online (Sandbox Code Playgroud)

然后我决定使用自定义运算符而不是compose函数.自定义运算符是...起初我只是复制了compose函数并将其名称更改为...这是它的样子:

infix operator .. { associativity left }
func ..<A,B,C>(f:(B -> C))(g: (A -> B)) -> A -> C {
    return { f(g($0)) }
}
Run Code Online (Sandbox Code Playgroud)

这里Xcode给出了错误:"一元运算符实现必须有'前缀'或'后缀'修饰符"

之后我将操作符更改为:

infix operator .. { associativity left }
func ..<A,B,C>(f: (B -> C), g: (A -> B)) -> A -> C {
    return { f(g($0)) }
}
Run Code Online (Sandbox Code Playgroud)

并且odd功能如下:

func odd(value: Int) -> Bool {
    return (not..even)(value)
}
Run Code Online (Sandbox Code Playgroud)

或者作为封闭:

let odd = not..even
Run Code Online (Sandbox Code Playgroud)

这段代码很有用.现在我知道也许这里没有任何好处让..操作员在这里做咖喱但是我想知道为什么不允许咖喱操作员?例如,如果+运算符被定义为curried函数,我们将做这样的事情:

let array = [1,2,3,4]
array.map((+1))
Run Code Online (Sandbox Code Playgroud)

Cod*_*aFi 6

您需要一些称为运算符部分的东西,或者能够在左侧或右侧部分应用二元运算符.不幸的是,Swift只允许完全没有问题的运营商,这意味着你必须要有一点创意.如果我们将运算符视为二元函数op : (A, A) -> A,那么它的curried形式curry-op : A -> A -> A只是一个返回一元函数的一元函数.我们可以使用分别模拟左右分区的自定义前缀和后缀运算符来伪装它.

这是前缀和后缀+

prefix func +<A : protocol<IntegerLiteralConvertible, IntegerArithmeticType>>(r : A) -> (A -> A) {
    return { l in l + r }
}

postfix func +<A : protocol<IntegerLiteralConvertible, IntegerArithmeticType>>(l : A) -> (A -> A) {
    return { r in l + r }
}
Run Code Online (Sandbox Code Playgroud)

这允许您编写诸如此类的代码

let l = [Int](1...10) /// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
l.map(+5) /// [6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Run Code Online (Sandbox Code Playgroud)

而不是旧的

l.map({ x in x + 5 })
Run Code Online (Sandbox Code Playgroud)