Variadic Generics


(Adam Sharp) #21

Another example that takes a different shape: a library I’ve contributed to, Curry, currently defines function currying for up to 21 arguments:

public func curry<A, B, C>(_ function: @escaping ((A, B)) -> C) -> (A) -> (B) -> C {
    return { (a: A) -> (B) -> C in { (b: B) -> C in function((a, b)) } }

This is unlike the zip-style function in that it needs to be able to unpack/repack the types involved. It would be quite cool to be able to define this with a single generic function!

(Andrea Tomarelli) #22

That is another interesting example, but unfortunately I can't figure out how VG may help here - it may be the late hour! I can't wrap my head about both how to specify the parameter of the variadic curry function and its body.
The problem is that this function feel somehow / something recursive.

Edit: maybe with head / tail variadic unpacking? With the support of other totally invented stuff:

// Invented syntax:
// #dropLast(T) returns the variadic generic `T` but the last one
// #last(T) returns the last element of the variadic generic `T`
// #expand(v) expands / unpack a variadic *value* into the surrounding context

// base case
func curry<A, B, C>(_ f: @escaping ((A, B)) -> C) -> (A) -> (B) -> C {
  return { a in { b in f((a, b)) } }

// recurring case
func curry<...T>(_ f: @escaping (#dropLast(T)) -> #last(T)) -> <# what to put here? #> {
  return { h in curry({ t in f(h, #expand(t)) }) }

(Andrea Tomarelli) #23

Added link on the opening post to a partially completed document about this topic!