Is it possible to assign a generic function to a variable? - swift

func function1(arg: Int) -> Int { return arg }
func function2<T>(arg: T) -> T { return arg }
let f1 = function1 // No problem
let f2 = function2<Int> // Cannot explicitly specialize a generic function
A current short coming of the language?

You can let Swift infer the specialization of function2 by the explicit type annotation of f2:
let f2: (Int) -> Int = function2
Alternatively, use an intermediate specializer function which supplies the explicit type annotation
func specialize1Dmap<T>(_ f: #escaping (T) -> T, as _: T.Type) -> (T) -> T { return f }
let f2int = specialize1Dmap(function2, as: Int.self)
let f2str = specialize1Dmap(function2, as: String.self)

Related

Generic parameter 'Arg' could not be inferred - generic memoization function

I'm trying to build a generic memoization function
func memoize<Arg: Hashable, Ret>(_ fn: #escaping ((Arg) -> Ret)) -> ((Arg) -> Ret) {
var cache: [Arg:Ret] = [:]
func inner (x: Arg) -> Ret {
let ret = cache[x, default: fn(x)]
cache[x] = ret
return ret
}
return inner
}
But I am unable to define my function as a closure for some reason
struct Foo: Hashable {
let a: String
let b: String
}
let foo = memoize(
(x: Foo) -> String in {
print("miss")
return x.a
}
)
Cannot convert value of type '((Foo) -> String).Type' to expected argument type '(Arg) -> Ret'
Generic parameter 'Arg' could not be inferred
why is that?
Your closure syntax is incorrect. The signature part goes inside of the { } (See Closure Expression Syntax):
let foo = memoize(
{ (x: Foo) -> String in
print("miss")
return x.a
}
)
You can also omit the () (known as a trailing closure), which is more idiomatic:
let foo = memoize {
(x: Foo) -> String in
print("miss")
return x.a
}

Ignore "unused" warning in Swift when use a "pointer" to func?

I know that I should use #discardableResult. So I have the following code:
#discardableResult func someFunc() { ... }
Then I just call it:
someFunc()
But if I have and use a pointer to this method then it doesn't work again. For example:
let someFunc = self.someFunc
someFunc() //unused warning
Is it possible to avoid _=someFunc() in this case?
Unfortunately, discardableResult only applies to method/function declarations. What you can do is to wrap the value-returning function in a void-returning closure:
#discardableResult
func f() -> Int { return 1 }
// the type annotation here is important
let someFunc: () -> Void = { f() }
Alternatively, write a function that "erases" the return type of functions:
func discardResult<R>(_ f: #escaping () -> R) -> (() -> Void) {
{ _ = f() }
}
let someFunc = discardResult(f)
The downside is that you need to write an overload of this for each arity:
func discardResult<T, R>(_ f: #escaping (T) -> R) -> ((T) -> Void) {
{ x in _ = f(x) }
}
func discardResult<T, U, R>(_ f: #escaping (T, U) -> R) -> ((T, U) -> Void) {
{ x, y in _ = f(x, y) }
}
func discardResult<T, U, V, R>(_ f: #escaping (T, U, V) -> R) -> ((T, U, V) -> Void) {
{ x, y, z in _ = f(x, y, z) }
}
// and so on

Swift: generic overloads, definition of "more specialized"

In the below example, why is the foo(f) call ambiguous?
I understand that the second overload could also apply with P == (),
but why isn't the first one considered more specialized,
and therefore a better match?
func foo<R>(_ f: () -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }
let f: () -> Int = { 42 }
foo(f) // "Ambiguous use of 'foo'"
I'd say your problem is that you don't explicitely tell the compiler that P == ()
try the following code in a playground :
Void.self == (Void).self // true
Void() == () // true
(Void)() == () // true
(Void) == () // Cannot convert value of type '(Void).Type' to expected argument type '()'
Foo<Int>.self == (() -> Int).self // false
(() -> Int).self == ((Void) -> Int).self // false
Foo<Int>.self == ((Void) -> Int).self // true
Since (Void) cannot be converted to (), I guess the compiler can't understand that foo<R>(_ f: () -> R) is actually a specialization of foo<P, R>(_ f: (P) -> R).
I suggest you create generic type aliases for your function types to help the compiler understand what you're doing eg. :
typealias Bar<P, R> = (P) -> R
typealias Foo<R> = Bar<Void, R>
Now you can can define your function like that :
func foo<R>(_ f: Foo<R>) { print("r") } // Note that this does not trigger a warning.
func foo<P, R>(_ f: Bar<P, R>) { print("pr") }
and then use them with any closure you want :
let f: () -> Int = { 42 }
foo(f) // prints "r"
let b: (Int) -> Int = { $0 }
foo(b) // prints "pr"
let s: (String) -> Double = { _ in 0.0 }
foo(s) // prints "pr"
But you can actually just write :
func foo<R>(_ f: (()) -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }
or even :
func foo<R>(_ f: (Void) -> R) { print("r") } // triggers warning :
// When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?
func foo<P, R>(_ f: (P) -> R) { print("pr") }
and you get the same results.

Non-escaping error when implementing Church Numerals in Swift 3

I am attempting to implement Church Numerals in Swift 3. Currently, I have:
func numToChurch(n: Int) -> ((Int) -> Int) -> Int {
return { (f: (Int) -> Int) -> (Int) -> Int in
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
func churchToNum(f: ((Int) -> Int) -> (Int)-> Int) -> Int {
return f({ (i : Int) -> Int in
return i + 1
})(0)
}
At this line in my function numToChurch:
return f(numToChurch(n: n - 1)(f)(x))
I keep getting a compile-time error that "Closure of non-escaping parameter 'f' may allow it to escape". As a quick-fix, I accepted the recommended changes to include #escaping:
func numToChurch(n: Int) -> ((Int) -> Int) -> Int {
return { (f: #escaping (Int) -> Int) -> (Int) -> Int in
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
But even after making the changes, I keep getting told the same error and it recommends adding another #escaping after "f:". I understand that this has to do with marking function parameters as #escaping to tell the compiler that the parameters can be stored or captured for functional programming. But I don't understand why I keep getting this error.
Original non-escaping question resolved
Help with understanding church encoding in Swift cont:
func zero(_f: Int) -> (Int) -> Int {
return { (x: Int) -> Int in
return x
}
}
func one(f: #escaping (Int) -> Int) -> (Int) -> Int {
return { (x: Int) in
return f(x)
}
}
func two(f: #escaping (Int) -> Int) -> (Int) -> Int {
return { (x: Int) in
return f(f(x))
}
}
func succ(_ f: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
return { (f : #escaping ((Int) -> Int)) -> Int in
return { (x : Int) -> Int in
return f(n(f)(x))
}
}
}
func sum(m: #escaping ((Int) -> (Int) -> Int)) -> ((Int) -> (Int) -> Int) -> (Int) -> (Int) -> Int {
return { (n: #escaping ((Int) -> Int)) -> (Int) -> (Int) -> Int in
return { (f: Int) -> (Int) -> Int in
return { (x: Int) -> Int in
return m(f)(n(f)(x))
}
}
}
You're using currying for multi-parameter functions. That isn't a very natural way to express things in Swift and it's making things complicated. (Swift is not a functional programming language.)
As your linked article says, "All Church numerals are functions that take two parameters." So do that. Make it a two parameter function.
typealias Church = (_ f: ((Int) -> Int), _ x: Int) -> Int
This is a function that takes two parameters, a function and its argument.
Now you want to wrap the argument in the function N times:
// You could probably write this iteratively, but it is pretty elegant recursively
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return { (_, n) in n } }
// Otherwise, recursively apply the function
return { (f, x) in
numToChurch(n - 1)(f, f(x))
}
}
And getting back is just applying the function:
func churchToNum(_ church: Church) -> Int {
return church({$0 + 1}, 0)
}
Just building up on this, you can curry it (and I think I'm just saying what #kennytm has also answered). Currying is just slightly more complicated in Swift:
typealias Church = (#escaping (Int) -> Int) -> (Int) -> Int
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return { _ in { n in n } } }
return { f in { x in
numToChurch(n - 1)(f)(f(x))
}
}
}
func churchToNum(_ church: Church) -> Int {
return church({$0 + 1})(0)
}
There's a very reasonable question: "Why do I need #escaping in the second case, but not in the first?" The answer is that when you pass the function in a tuple, you've already escaped it (by storing it in another data structure), so you don't need to mark it #escaping again.
To your further questions, using a typealias dramatically simplifies this problem and helps you think through your types much more clearly.
So what are the parameters of zero? Nothing. It's a constant. So what should its signature be?
func zero() -> Church
How do we implement it? We apply f zero times
func zero() -> Church {
return { f in { x in
x
} }
}
One and two are nearly identical:
func one() -> Church {
return { f in { x in
f(x)
} }
}
func two() -> Church {
return { f in { x in
f(f(x))
} }
}
What is the signature of succ? It takes a Church and returns a Church:
func succ(_ n: #escaping Church) -> Church {
Because this is Swift, we need a little nudge by adding #escaping and _ to make things more natural. (Swift is not a functional language; it decomposes problems differently. Composing functions is not its natural state, so the over-abundence of syntax should not shock us.) How to implement? Apply one more f to n:
func succ(_ n: #escaping Church) -> Church {
return { f in { x in
let nValue = n(f)(x)
return f(nValue)
} }
}
And again, what is the nature of sum? Well, we're in a currying mood, so that means it's a function that takes a Church and returns a function that takes a Church and returns a Church.
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church
Again, a little extra syntax is needed because Swift. (And as above I've added an extra let binding just to make the pieces a little more clear.)
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church {
return { m in { f in { x in
let nValue = n(f)(x)
return m(f)(nValue)
} } }
}
The deep lesson here is the power of the Church typealias. When you try to think of Church numbers as "functions that blah blah blah" you quickly get lost in the curry and syntax. Instead, abstract them to be "Church numbers" and just think about what every function should take and return. Remember that a Church number is always a function that takes an Int and returns an Int. It never grows or shrinks from that no matter how many times it's been nested.
It's worth taking this example in a couple of other directions because we can play out some deeper ideas of FP and also how Swift should really be written (which are not the same....)
First, writing Church numbers in pointed style is...inelegant. It just feels bad. Church numbers are defined in terms of functional composition, not application, so they should be written in a point-free style IMO. Basically, anywhere you see { f in { x in ...} }, that's just ugly and over-syntaxed. So we want functional composition. OK, we can dig into some experimental stdlib features and get that
infix operator ∘ : CompositionPrecedence
precedencegroup CompositionPrecedence {
associativity: left
higherThan: TernaryPrecedence
}
public func ∘<T, U, V>(g: #escaping (U) -> V, f: #escaping (T) -> U) -> ((T) -> V) {
return { g(f($0)) }
}
Now, what does that do for us?
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return zero() }
return { f in f ∘ numToChurch(n - 1)(f) }
}
func succ(_ n: #escaping Church) -> Church {
return { f in f ∘ n(f) }
}
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church {
return { m in { f in
n(f) ∘ m(f)
} }
}
So we don't need to talk about x anymore. And we capture the essence of Church numbers much more powerfully, IMO. Summing them is equivalent to functional composition.
But all that said, IMO this is not great Swift. Swift wants structure and methods, not functions. It definitely doesn't want a top-level function called zero(). That's horrible Swift. So how do we implement Church numbers in Swift? By lifting into a type.
struct Church {
typealias F = (#escaping (Int) -> Int) -> (Int) -> Int
let applying: F
static let zero: Church = Church{ _ in { $0 } }
func successor() -> Church {
return Church{ f in f ∘ self.applying(f) }
}
static func + (lhs: Church, rhs: Church) -> Church {
return Church{ f in lhs.applying(f) ∘ rhs.applying(f) }
}
}
extension Church {
init(_ n: Int) {
if n <= 0 { self = .zero }
else { applying = { f in f ∘ Church(n - 1).applying(f) } }
}
}
extension Int {
init(_ church: Church) {
self = church.applying{ $0 + 1 }(0)
}
}
Int(Church(3) + Church(7).successor() + Church.zero) // 11
#escaping is part of the argument type, so you need to do it like:
func numToChurch(n: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
// ^~~~~~~~~
Complete, working code:
func numToChurch(n: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
// ^~~~~~~~~ ^~~~~~
return { (f: #escaping (Int) -> Int) -> (Int) -> Int in
// ^~~~~~~~~
if n == 0 {
return { x in x }
} else {
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
}
func churchToNum(f: (#escaping (Int) -> Int) -> (Int) -> Int) -> Int {
// ^~~~~~~~~
return f({ (i : Int) -> Int in
return i + 1
})(0)
}
let church = numToChurch(n: 4)
let num = churchToNum(f: church)
Note:
Your return type of numToChurch is wrong even without the #escaping part. You are missing a -> Int.
I have added the base n == 0 case in numToChurch, otherwise it will be an infinite recursion.
Since the result of numToChurch has an escaping closure, the same annotation needs to be added to that of churchToNum as well.

Generic typealias in Swift

In haskell you can do this:
type Parser a = String -> [(a, String)]
I tried to make something similar in Swift. So far I wrote these codes with no luck.
typealias Parser<A> = String -> [(A, String)]
typealias Parser a = String -> [(a, String)]
typealias Parser = String -> [(A, String)]
So is this simply impossible in swift? And if it is is there another ways to implement this behavior?
UPDATE: It seems generic typealiases are now supported in swift 3
https://github.com/apple/swift/blob/master/CHANGELOG.md
Generic typealias can be used since Swift 3.0. This should work for you:
typealias Parser<A> = (String) -> [(A, String)]
Here is the full documentation: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/typealias-declaration
Usage (from #Calin Drule comment):
func parse<A>(stringToParse: String, parser: Parser)
typealias cannot currently be used with generics. Your best option might be to wrap the parser function inside a struct.
struct Parser<A> {
let f: String -> [(A, String)]
}
You can then use the trailing closure syntax when creating a parser, e.g.
let parser = Parser<Character> { string in return [head(string), tail(string)] }
Generic Type Aliases - SE-0048
Status: Implemented (Swift 3)
The solution is straight-forward: allow type aliases to introduce type parameters, which are in scope for their definition. This allows one to express things like:
typealias StringDictionary<T> = Dictionary<String, T>
typealias IntFunction<T> = (T) -> Int
typealias MatchingTriple<T> = (T, T, T)
alias BackwardTriple<T1, T2, T3> = (T3, T2, T1)
Here I am presenting example for typealias that demonistrate you to how to use typealias in protocols definitions: I hope this helps you understand typealias
protocol NumaricType {
typealias elementType
func plus(lhs : elementType, _ rhs : elementType) -> elementType
func minus(lhs : elementType, _ rhs : elementType) -> elementType
}
struct Arthamatic :NumaricType {
func addMethod(element1 :Int, element2 :Int) -> Int {
return plus(element1, element2)
}
func minusMethod(ele1 :Int, ele2 :Int) -> Int {
return minus(ele1, ele2)
}
typealias elementType = Int
func plus(lhs: elementType, _ rhs: elementType) -> elementType {
return lhs + rhs
}
func minus(lhs: elementType, _ rhs: elementType) -> elementType {
return lhs - rhs
}
}
Output:
let obj = Arthamatic().addMethod(34, element2: 45) // 79