3

I was messing around with the functional programming in Swift 2.1, trying to implement the Church encoding pair/cons function (cons = λx λy λf f x y in untyped lambda calculus), which I had read couldn't be done in earlier versions of Swift.

With generics it looks like

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

which doesn't work, and gives an error I cannot understand (surely parameter list of type (Int,Int) can match generic type variables (S,T)?)

If you get rid of the generic types, and declare them all Ints, the function works, but of course we want to be able to cons together lists longer than 2; consing a list of length 3 is consing an Int with an (Int,Int) -> Int, for example.

Another option is to type everything as Any (see Type Casting for Any and AnyObject), but I couldn't make that work either.

Do you have any ideas? Is this possible in Swift yet? I'm sure there are simpler ways to implement cons/car/cdr, but I'm specifically interested in the Church encoding, where the list elements are arguments to anonymous functions (lambdas).

ziggurism
  • 2,264
  • 2
  • 16
  • 23
  • The problem is that in `cons(1,2)`, the Swift compiler cannot infer the type `U` from the context. – Martin R Nov 08 '15 at 18:23
  • [This very nice blog post](http://www.jonmsterling.com/posts/2011-12-28-expressing-church-pairs-with-types.html) by Jonathon Sterling talks a little about how the naive pair encoding in the untyped lambda calculus needs to be modified for a typed lambda calculus, and implements it in Haskell. Perhaps I should be thinking along these lines for Swift. – ziggurism Nov 08 '15 at 22:02
  • I also saw [these notes](http://www.mathstat.dal.ca/~selinger/papers/lambdanotes.pdf) on lambda calculus by Peter Selinger which discuss pair formation in the untyped lambda calculus and polymorphic lambda calculus ([System F](https://en.wikipedia.org/wiki/System_F)), but for simply typed lambda calculus, the pair type is not constructed (see [Why is there no product type in simply typed lambda-calculus?](http://mathoverflow.net/questions/151240/why-is-there-no-product-type-in-simply-typed-lambda-calculus)). This question seems to require more theoretical background than I am prepared for. – ziggurism Nov 08 '15 at 23:25
  • I thought it might be educational to try the same thing in Haskell, but I ran into the same type error. On the other hand, Wikipedia claims that system F is implemented in Haskell, so the theoretical typed polymorphic lambda calculus version of the Church encoding of the pair should be implementable. A [new stackoverflow question](http://stackoverflow.com/questions/33656979/implement-in-haskell-the-church-encoding-of-the-pair-for-polymorphic-λ-calculus/) reveals the answer: – ziggurism Nov 15 '15 at 14:50
  • implementing this requires higher rank polymorphism. So I think my conclusion is that it cannot be done without higher rank polymorphism, and Swift lacks higher rank polymorphism, hence the Church encoding of the pair cannot be implemented in Swift. – ziggurism Nov 15 '15 at 14:50

1 Answers1

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 one of type is an 'extra' type and could not be inferred by compilator. if you define the types, you can see, that not all combinations are valid. Just define the output type and the compilator should be happy

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)
user3441734
  • 16,722
  • 2
  • 40
  • 59