Typecase regular Swift function to Curry Function
You don't typecast it, you return nested closures that capture each parameter in turn:
func add(x: Int, y: Int) -> Int {
return x + y
}
func curry<T1, T2, T3>(f: (T1, T2) -> T3) -> T1 -> T2 -> T3 {
return {
(t1: T1) -> T2 -> T3 in
return {
(t2: T2) -> T3 in
return f(t1, t2)
}
}
}
let curriedAdd = curry(add)
let add3 = curriedAdd(3)
println(add3(5))
// 8
This is more succinct:
func curry<T1, T2, T3>(f: (T1, T2) -> T3) -> T1 -> T2 -> T3 {
return { t1 in { t2 in f(t1, t2) } }
}
I thought it would be fun to write a curry maker; here it is - if anyone knows how to make one of these that generates an actual function that would be amazing:
func curryRecipe(n: Int) -> String {
let types = join(", ", map(1...n, { "T\($0)" }))
let returnType = join(" -> ", map(1...n, { "T\($0)" }))
let closures = join(" in ", map(1...n, { "{ t\($0)" }))
let braces = join(" ", Array(count: n, repeatedValue: "}"))
return "func curry<\(types), R>(f: (\(types)) -> R) -> \(returnType) -> R {\r" +
" return \(closures) in f(\(types.lowercaseString)) \(braces)\r}"
}
println(curryRecipe(15))
Output:
func curry<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R>(f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R) -> T1 -> T2 -> T3 -> T4 -> T5 -> T6 -> T7 -> T8 -> T9 -> T10 -> T11 -> T12 -> T13 -> T14 -> T15 -> R {
return { t1 in { t2 in { t3 in { t4 in { t5 in { t6 in { t7 in { t8 in { t9 in { t10 in { t11 in { t12 in { t13 in { t14 in { t15 in f(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) } } } } } } } } } } } } } } }
}
Curry Function in Swift
You can achieve this pretty easily with closures:
/// Takes a binary function and returns a curried version
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a, b) } }
}
curry(+)(5)(6) // => 11
let add: Int -> Int -> Int = curry(+)
add(5)(6) // => 11
It would be really nice to be able to do the same thing for functions that take 3, 4 or more arguments, but without duplicating the implementation. The signature of such a function might start something like:
/// Take a function accepting N arguments and return a curried version
func curry<T>(args: T...) -> /* ? */
What would the return type be? It would change based on the input to the function. This definitely isn't possible in Swift at the moment, and I don't think it would be possible at all without some kind of macro system. But even with macros I don't think the compiler would be satisfied unless it knew the length of the list at compile-time.
Having said that, it's really straight-forward to manually overload the currying function with a version that accepts 3, 4, 5 or more parameters:
func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
return { a in { b in { c in f(a,b,c) } } }
}
func curry<A,B,C,D,E>(f: (A, B, C, D) -> E) -> A -> B -> C -> D -> E {
return { a in { b in { c in { d in f(a,b,c,d) } } } }
}
// etc.
How to write a flip method in Swift?
A->B->C
is the type of a function taking one argument of type A
and returning a function B->C
(a "curried" function). The type of a function taking
two arguments is (A, B)->C
:
func flip<A, B, C>(f: (A, B)->C) -> (B, A)->C {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
let x = flip(-)(10, 5)
println(x) // -5
It can slightly be shortened to
func flip<A, B, C>(f: (A, B)->C) -> (B, A)->C {
return { (valueB, valueA) in
f(valueA, valueB)
}
}
due to automatic type inference.
As far as I know, Swift does not automatically convert functions
taking multiple arguments into curried functions, compare
Typecase regular Swift function to Curry Function.
What is a generalized uncurry function in Scheme, for a curry function of n parameter?
A generic uncurry
can be written to call a function, f
, with arguments, t
, one at a time -
(define ((uncurry f) . t)
(if (null? t)
f
(apply (uncurry (f (car t)))
(cdr t))))
Using it on (curry +)
will not work because +
is a variadic function. However, for functions of known arity, it works just fine -
(define (plus a b c)
(+ a b c))
((uncurry (curry plus)) 1 2 3) ; 6
If you don't supply all three arguments, the "remainder" of the curried function will be returned -
(((uncurry (curry plus)) 1 2) 3) ; 6
((((uncurry (curry plus)) 1) 2) 3) ; 6
(((((uncurry (curry plus))) 1) 2) 3) ; 6
Subsequent calls to uncurry
could be used if additional arguments need to be supplied at a later time -
((uncurry ((uncurry (curry plus)) 1)) 2 3) ; 6
However, if you try to apply too many arguments, a run time error will be raised -
((uncurry (curry plus)) 1 2 3 4) ; error, expected procedure; 6 given
Is there a way to perform a generalized uncurry function on curried, variadic functions? That was what the question was referring to with "generalized", needs to be able to work on a variable number of arguments.
I recommend you see molbdnilo's comment on your question. You cannot effectively curry
a variadic function like +
because currying is the abstraction of arity. To put this another way, if +
can take 0 to infinite arguments, how many applied arguments should (curry +)
take before it returns a sum rather than a function?
Maybe you are looking for partial
application?
(define ((partial f . a) . b)
(apply f (append a b)))
((partial + 1 2)) ; 3
((partial + 1) 2) ; 3
((partial +) 1 2) ; 3
pattern match in curry function: which paramter to match against
Let's step through your function:
1.We apply the first parameter "b" to curr3
and get back a function that takes a string and gives us back a string:
val first:String => String = curr3("b")
which is equivalent to (basically we've thrown away the first parameter n
):
val first:String => String = {
case "a" => "a"
case "b" => "b"
}
2.We apply the second parameter to first and get back "a":
val second:String = first("a")
println(second) // prints a
So the first parameter is taken in but never used. If you want to match on the first parameter you could do this:
def curr3(n: String): String => String = s => n match {
case "a" => "a"
case "b" => "b"
}
But now we're just throwing away the second parameter s
. I think you don't really need a curried function here (unless you want to do something with the second paramater) and you could do something simple similar to the first example:
def curr3(n: String) = n match {
case "a" => "a"
case "b" => "b"
}
Understanding Generic Functions in Common Lisp?
What value would creating a generic functions add?
I like to declare the generic function explicitly because it is possible to add documentation and declarations that are relative to the generic function (optimize for speed/space/debug), and other details such as method combination (a.k.a. when you have multiple methods applicable for a given call, this defines which are executed and in which order). Here for example I can define talk
as having a progn
method combination (all methods are executed as-if encapsulated in a progn
form):
(defgeneric talk (subject)
(:documentation "Say something to standard output")
(:method-combination progn))
This is a bit contrived example, but here we go:
(defclass human () ())
(defmethod talk progn ((a human))
(print "hello"))
(defclass wolf () ())
(defmethod talk progn ((a wolf))
(print "owooooo!"))
(defclass werewolf (human wolf) ())
Defining a class that inherits from both means that a call to talk
for an instance of the class can execute two methods (sorted in a somewhat topological order called the Method Resolution Order). So with this method combination all the methods are executed:
* (talk (make-instance 'werewolf))
"hello"
"owooooo!"
But, I would say that being able to document the generic function is by itself a good enough reason to declare it with defgeneric
.
Why are generic functions useful?
If you define talk
as a generic function you allow any class to participate in code that calls talk
(e.g. a library), this is a way to allow extensions without having to close the set of possible values, unlike using something like typecase
in a function where you can only list a predefined set of cases.
For example the standard functions print-object
is called at various times in your Lisp implementation (in the inspector, the REPL, the debugger), if you want you can implement a method for your custom types without having to hack the internals of your environment.
Are they like instances in other OO languages that provide structure?
Generic functions are, unlike in other OO languages, not tied to a single class or instance. They can be specialized1 on more than one argument, which means none of them "owns" the generic function.
1. specialized is defined as follows:
specialize v.t. (a generic function) to define a method for the generic function, or in other words, to refine the behavior of the generic function by giving it a specific meaning for a particular set of classes or arguments.
The idea behind this is that methods can be more or less specific: a method of two arguments a
and b
that specializes both on (a number)
and (b string)
is more specific than another one that specializes only on (b vector)
, and methods are actually sorted from the most specific to the least specific ones (resp. from the least to the most) when combining them. You can even specialize a function on (a (eql 10))
to cover only the specific case of an argument a
being eql
to 10.
Related Topics
How Do Uniqueness Constraints as (Comma,Separated,Attributes) Work with Swift in Coredata
Swift 4: How to Asynchronously Use Urlsessiondatatask But Have The Requests Be in a Timed Queue
How to Pass Data from Using Post/Form Leaf Template
Nskeyedunarchiver Decodeobjectforkey: Cannot Decode Object of Class for Key (Ns.Objects)
Swift Flatmap on Array with Elements Are Optional Has Different Behavior
How to Find Multiple Nsrange for a String from Full String iOS Swift
Cannot Convert Value of Type 'Nsmutablearray' to Expected Argument Type '[Skaction]'
Swift Unsafemutablepointer & Unsafemutablepointer<Unsafepointer<Sometype>>
Automatically Reload Tableviewcontroller on Rewind
Trouble Calling a Method in an Init
Passing Data Between 2 View Controllers in Swift
How to Separate The Date and Time Components of Nsdate() in Swift
Extension for Average to Return Double from Numeric Generic
Is There a Simple Way to Test If You Match One of a Set of Enumerations
Loading Image from Remote Url Asynchronously in Swiftui Image Using Combine's Publisher