Быстрая функция высшего порядка (церковная пара или минусы) с общими типами параметров, не принимающими типы входных параметров

Я возился с функциональным программированием в Swift 2.1, пытаясь реализовать функцию пары / минусы кодирования Черча ( cons = λx λy λf fxy в нетипизированном лямбда-исчислении), которую, как я читал, нельзя было сделать в более ранних версиях Swift.

С дженериками это выглядит так

func cons<S,T,U>(x:S,_ y:T) -> ((S,T) -> U) -> U
{
    return { (f:((S,T) -> U)) -> U in return f(x,y)}
}

cons(1,2)
//error: cannot invoke 'cons' with an argument list of type '(Int, Int)'
//note: expected an argument list of type '(S, T)'

который не работает и выдает ошибку, которую я не могу понять (конечно, список параметров типа (Int,Int) может соответствовать переменным универсального типа (S,T)?)

Если вы избавитесь от универсальных типов и объявите их как целые числа Ints, функция сработает, но, конечно, мы хотим иметь возможность объединять списки длиннее 2; список из длины 3 состоит, например, из Int с (Int,Int) -> Int.

Другой вариант - напечатать все как Any (см. приведение типов для Any и AnyObject), но я не мог заставить это работать.

Есть ли у вас какие-либо идеи? Это возможно в Swift еще? Я уверен, что есть более простые способы реализации cons/car/cdr, но я особенно заинтересован в кодировке Черча, где элементы списка являются аргументами анонимных функций (лямбда-выражения).

1 ответ

func cons<S,T,U>(x:S,_ y:T) -> ((S,T) -> U) -> U
{
    return { (f:((S,T) -> U)) -> U in return f(x,y)}
}

let i: ((Int,Int)->Int)->Int = cons(1,2)
let d: ((Int,Int)->Double)->Double = cons(2,3)
let e: ((Double,Int)->String)->String = cons(2.2, 1)
let e: ((Double,Int)->Double)->Double = cons(2.2, 1)

Стил один из типа является "дополнительным" типом и не может быть выведен компилятором. если вы определите типы, вы увидите, что не все комбинации являются действительными. Просто определите тип вывода, и компилятор должен быть счастлив

func cons<S,T, U>(x:S,_ y:T, outptAs: U.Type) -> ((S,T) -> U ) -> U
{
    return { (f:((S,T) -> U)) -> U in return f(x,y) }
}

let i = cons(1.2 ,"A", outptAs: Int.self)
let j = cons("alfa","beta", outptAs: Double.self)
Другие вопросы по тегам