Неугомонная функция карри в Swift - PullRequest
0 голосов
/ 30 января 2019

У меня есть функция, которая принимает два аргумента и возвращает одно значение.

Например,

func sum(x: Int, y: Int) -> Int {
    return x + y
}

Следующим шагом является использование currying для получения функции, которая принимаетединственный первый аргумент и вернуть замыкание с соответствующей подписью.Кроме того, я написал псевдоним типа для большей ясности типа результата.

typealias EscapingClosure<A, B> = (A) -> B
func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> EscapingClosure<A, (B) -> C> {
    return { (a: A) -> ((_ b: B) -> C) in
        return { (b: B) -> C in f(a, b) }
    }
}

Но потом я вспомнил о функции uncurry, которая должна возвращать сигнатуру функции sum по умолчанию, если я ее применю.на карри результат.Поэтому я попытался реализовать вариант uncurry, и что я получу в результате:

func uncarry<A, B, C>(_ f: @escaping EscapingClosure<A, (B) -> C>) -> (A, B) -> C {
    return { (a: A, b: B) -> C in
        return f(a)(b)
    }
}

Но вот проблема - я не могу использовать эту функцию uncurry с результатомcurry для функции sum, потому что uncurry требует только @ escape-параметра , где curryied функция возвращает неэкранируемый вариант.

Вот ошибка компилятора Swift:

Cannot convert value of type '((A) -> Void) -> ()' to expected argument type '(_) -> (_) -> _'

Кто-нибудь знает, есть ли какие-либо способы создания функции uncurry в Swift, которые были бы применимы к результату функции карри.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Ваша функция uncurry может выполнять только такие функции без каррирования:

let currableSum = curry(sum)
let uncurriedSum = uncurry(currableSum)

let add100 = currableSum(100)
print(add100(23)) // => 123

print(uncurriedSum(2, 2)) // => 4

Проблема заключается в том, что вы ошибаетесь, если вы не приняли приложение.После того, как вы частично или полностью применили карри-функцию (или любую другую функцию), у вас не будет механизма, чтобы вернуться к исходной функции, которая дала результат.

uncurry(add100) // ❌ can't "unapply" a partially applied function

Представьте, если бы это было так.Каждое целое число, строка и другое значение должны помнить историю того, какие функции вызвали это.Я не могу придумать ни одного варианта использования для этого.Во-первых, для этого потребуется динамическая типизация (или принудительное приведение во время компиляции в статическом языке, таком как Swift), потому что вы не можете предсказать сигнатуру произвольной функции, которая дает заданный результат.

0 голосов
/ 30 января 2019

Как пишет @Alexander выше, я могу легко использовать функцию uncurry для результата каррирования sum().

Я только что сделал ошибку, когда передал значение результата функции карри.

...