Быстрая функция высшего порядка (церковная пара или минусы) с общими типами параметров, не принимающими типы входных параметров
Я возился с функциональным программированием в 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)