3

я бездельничал с функциональным программированием в Swift 2.1, пытаясь реализовать Church encoding pair/cons функции (cons = Хе λy λf FXY в нетипизированном lambda calculus), который у меня был read, не удалось сделать в более ранних версиях Swift.Swift функция высшего порядка (церковь пара аки минусы) с родовыми типами параметров не принимают типов параметров ввода

С generics это выглядит как

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) ?)

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

Другой вариант - набрать все как Any (см. Type Casting for Any and AnyObject), но я тоже не мог сделать эту работу.

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

+0

Проблема в том, что в 'cons (1,2)' компилятор Swift не может вывести тип 'U' из контекста. –

+0

[Это очень приятное сообщение в блоге] (http://www.jonmsterling.com/posts/2011-12-28-expressing-church-pairs-with-types.html) Джонатана Стерлинга немного рассказывает о том, как наивная пара кодирование в нетипизированном лямбда-исчислении необходимо изменить для типизированного лямбда-исчисления и реализовать его в Haskell. Возможно, я должен подумать об этом для Свифта. – ziggurism

+0

Я также видел [эти заметки] (http://www.mathstat.dal.ca/~selinger/papers/lambdanotes.pdf) на исчислении лямбда Петром Селингером, которые обсуждают образование пар в нетипизированном лямбда-исчислении и полиморфном лямбда-исчислении ([System F] (https://en.wikipedia.org/wiki/System_F)), но для просто типизированного лямбда-исчисления тип пары не построен (см. [Почему нет типа продукта в просто типизированном лямбда-исчислении? ] (http://mathoverflow.net/questions/151240/why-is-there-no-product-type-in-simply-typed-lambda-calculus)). Этот вопрос, кажется, требует более теоретического фона, чем я готов. – ziggurism

ответ

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) 

stil один из типов является «дополнительным» типом и не может быть выведен компилятором. если вы определяете типы, вы можете видеть, что не все комбинации действительны. Просто определите тип вывода, и компилятор должен быть счастлив

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)