# Equality of functions

**URL:** <https://forums.swift.org/t/equality-of-functions/30295>\
**Category:** Discussion\
**Tags:** equality, function\
**Created:** [October 30, 2019, 12:43am UTC](https://forums.swift.org/t/equality-of-functions/30295 "2019-10-30T00:43:47Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [November 1, 2019, 2:43pm UTC](https://forums.swift.org/t/equality-of-functions/30295/41 "2019-11-01T14:43:04Z")

</div>

Agreed. In fact, if it is not explicitly disallowed to have argument labels on `callAsFunction` methods, then we'd run into the following issue with function constraints that ignore labels:

```swift
struct Foo {
    func callAsFunction(bar: Int) -> Bool { return bar > 5 }
    func callAsFunction(baz: Int) -> Bool { return baz < 5 }
}

func call(f: (Int) -> Bool, x: Int) -> Bool {
    return f(x)
}

let y = Foo()

call(y, 5) // error: ambiguous conformance to (Int) -> Bool

```

I suppose that this isn't _that_ problematic, though, since a client can always trivially disambiguate:

```swift
call(y.callAsFunction(bar:), 5)

```

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 1, 2019, 2:57pm UTC](https://forums.swift.org/t/equality-of-functions/30295/42 "2019-11-01T14:57:14Z")

</div>

Did I understand correctly that in your example, `struct Foo` does not **declare** conformance to `(Int) -> (Int)`?

Because that would be one more special thing about function protocols. Currently any other protocol requires conformance to be explicitly declared, even if type already satisfies all the requirements:

```
protocol Foo { func foo() }
struct FooImpl { func foo() {} }
let foo: Foo = FooImpl() // ERROR

```

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [November 1, 2019, 3:11pm UTC](https://forums.swift.org/t/equality-of-functions/30295/43 "2019-11-01T15:11:13Z")

</div>

Ah good point, I didn't think about it from the angle of explicitly declaring conformance. Implementing `callAsFunction` does seem subtly different to me than implementing a method that happens to have the same name as something in a protocol, but I can see the argument for requiring `struct Foo: (Int) -> Bool`.

Then, if we wanted to allow labeled-argument `callAsFunction` definitions to conform, we'd need the declaration-site disambiguation syntax that has come up in the past (and IIRC already exists privately):

```swift
struct Foo: (Int) -> Bool {
    @satisfying((Int) -> Bool) func callAsFunction(bar: Int) -> Bool { ... }
}

```

Would `@satisfying(<function type>)` be applicable to _any_ member function with a matching type signature? And if so, would that make `callAsFunction` redundant? In the world where conformance to function types is declared explicitly, I may be convinced that requiring no argument labels is the right solution.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 1, 2019, 4:48pm UTC](https://forums.swift.org/t/equality-of-functions/30295/44 "2019-11-01T16:48:31Z")

</div>

> [@Nickolas\_Pohilets](#):
>
> This makes callable structs behave different from regular functions.
> 
> ```swift
> func p1(x: Float) -> Float { return x * x + 2 * x + 1 }
> let y1 = p1(x: 3.141) // Called with argument label
> let f1: (Float) -> Float = p1 // OK
> 
> ```

Not really, IMO. `p1` is a shorthand for referencing `p1(x:)`, assuming there's no ambiguity, which is a value of type `(Float) -> Float` today, or in the future could be considered an anonymous type that conforms to `any (Float) -> Float`. Even this is something we've discussed deprecating, because it's led to confusing behavior in the past. At a fundamental level, argument labels are part of declaration names, not of types.

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 1, 2019, 5:05pm UTC](https://forums.swift.org/t/equality-of-functions/30295/45 "2019-11-01T17:05:59Z")

</div>

Another thing that I cannot get my head around, is the relation between argument and result types and the protocol. They don't look like associated types, because they are specified from the outside. To me they look more like generic parameters. But Swift currently does not have generic protocols, and, as far as I understood, is not planning to have.

[Improving the UI of generics - #125 by anandabits](https://forums.swift.org/t/improving-the-ui-of-generics/22814/125) mentions the following syntax, which may somewhat resolve this:

```
typealias CollectionOf<T> = Collection where Self.Element == T

```

Should we say that `(Int) -> Void` is a syntax sugar for `Callable where Self.Args == (Int), Self.Result == Void`? Or `(Int) -> Void` is a non-nominal protocol and notions of both generic args and associated types do not apply.

As an example, let's say we want to write a generic middleware that prints all the args and result of a function call.

With generic arguments, it would look something like this (`variadic` keyword is from [swift-evolution/XXXX-variadic-generics.md at variadic-generics · technicated/swift-evolution · GitHub](https://github.com/technicated/swift-evolution/blob/variadic-generics/proposals/XXXX-variadic-generics.md)):

```
struct FunctionLogger<variadic Args, Result, F: (Arg) -> Result = any (Args) -> Result>: (Args) -> Result {
    var base: F

    func callAsFunction(_ args: Args) -> Result {
        print(args)...
        let result = base(args)
        print(result)
        return result
    }
}

```

And with associated types:

```
struct FunctionLogger<F: Callable>: Callbable {
    typealias Args = F.Args
    variadic typealias Result = F.Result

    var base: F

    func callAsFunction(_ args: Args) -> Result {
        print(args)...
        let result = base(args)
        print(result)
        return result
    }
}

```

Can the same struct conform to multiple function protocols? With generic arguments - yes, because `(Int) -> Void` and `(Float) -> Void` are **different** protocols. With associated types, there is only one protocol `Callable` and there can be only one conformance.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 1, 2019, 5:25pm UTC](https://forums.swift.org/t/equality-of-functions/30295/46 "2019-11-01T17:25:56Z")

</div>

You can think of a function type constraint as being like a protocol with associated types, but I'm not sure that's the best way to model them, because functions have modifiers that aren't types, such as `inout`/`owned`/`shared` arguments, `throws`, and maybe eventually `async`, pure, or other effect modifiers. I would think of a function constraint as being an ad-hoc requirement that a type has a `callAsFunction` method with a matching signature.

---

<div class="post-metadata">

**Author:** ![Mark\_Lilback](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mark_lilback/32/2901_2.png) [@Mark\_Lilback](https://forums.swift.org/u/Mark_Lilback)\
**Post date:** [November 1, 2019, 10:35pm UTC](https://forums.swift.org/t/equality-of-functions/30295/47 "2019-11-01T22:35:09Z")

</div>

> [@Nickolas\_Pohilets](#):
>
> The `@equatable` attribute probably is redudant. So far, I haven't encountered any example of type which conforms to Equatable, but has good reasons not to conform to Hashable.

Here's a class I have that is Equatable, but. the compiler won't generate a Hashable implementation. The AppFile class is Hashable.

```swift
class FileRowData: Equatable {
	var sectionName: String?
	var file: AppFile?
	init(name: String?, file: AppFile?) {
		self.sectionName = name
		self.file = file
	}
	static public func == (lhs: FileRowData, rhs: FileRowData) -> Bool {
		if lhs.sectionName != nil && lhs.sectionName == rhs.sectionName { return true }
		if rhs.file != nil && lhs.file != nil && lhs.file?.fileId == rhs.file?.fileId { return true }
		return false
	}
}

```

I implemented Equatable, but I have no need for Hashable, have no idea why one can't be generated, and do not want to spend time writing dead code.

This is the first example I found. A search finds 46 conformances to Equatable in this project. I tried Hashable when originally implemented, but it didn't work for any of these instances.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 1, 2019, 11:57pm UTC](https://forums.swift.org/t/equality-of-functions/30295/48 "2019-11-01T23:57:35Z")

</div>

The compiler does not autogenerate conformances to `Equatable` or `Hashable` for classes, because for mutable classes, it isn't safe to, since modifying a class's fields would change the hash and equality behavior of the "same" value.

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 2, 2019, 9:29am UTC](https://forums.swift.org/t/equality-of-functions/30295/49 "2019-11-02T09:29:19Z")

</div>

Off-topic: Why did you implement it as a class, and not a struct? Do you care about identity?

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 2, 2019, 9:58pm UTC](https://forums.swift.org/t/equality-of-functions/30295/50 "2019-11-02T21:58:11Z")

</div>

Should it be possible to downcast function existential to an existential with more protocols? Probably yes, works now for regular protocols.

```
let x1: Hashable & () -> Void = { print(42) }
let x2: () -> Void = { print(42) }
let y1 = (x1 as () -> Void) as? (Hashable & () -> Void) // .some(x1)
let y2 = x2 as? (Hashable & ()->Void) // nil

```

What would be the `type(of: x)`? Now it is `(() -> Void).self`. But if we treat `() -> Void` as an existential container, then it should return a type of the underlying compiler-generated struct, and that raises questions about compatibility.

Should code compiled with support of functions as protocols be binary compatible with code compiled with old compiler? In that case, can they have different runtimes, or we can assume that they have a shared runtime that supports all the new features? Is it possible to export two implementations of `type(of:)` from the runtime library - one for old code, one for new code? Probably `@_silgen_name` can help.

If we maintain compatibility, what should `type(of:)` report for the function created in old code? Some placeholder struct? Single struct for all function types, or one per type?

Also, when we have regular struct in an existential container and it is converted to `Any`, then original struct is placed into existential buffer and type of the original struct is recorded in `Any`, not the type of the existential container. But if we should maintain binary compatibility with older versions, we may have to break this rule and put function existential container into existential buffer of `Any`. Then new version of `type(of:)` and bunch of other functions should be ready to handle this and unpack two existential containers.

---

<div class="post-metadata">

**Author:** ![codafi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/codafi/32/791_2.png) [@codafi](https://forums.swift.org/u/codafi)\
**Post date:** [November 3, 2019, 5:00pm UTC](https://forums.swift.org/t/equality-of-functions/30295/51 "2019-11-03T17:00:33Z")

</div>

Intensional equality oughta be called “coincidental equality”. It is almost never what you actually want (cf, the “in algebra” reference), and only happens to work if you can convince some suitable reduction machinery to gin up two identical ASTs - or you introduce a rewrite mechanism to force its hand.

It’s also not relevant to the core issue here. I suggest we move away from the language of mathematics when discussing this topic. While it’s certainly cool to bring up constructive math (and all the fun stuff Baire Spaces let you do) none of that generalizes.

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 7, 2019, 9:57am UTC](https://forums.swift.org/t/equality-of-functions/30295/52 "2019-11-07T09:57:51Z")

</div>

Discussion seems to get stuck a bit.

@Joe_Groff, @anandabits, any comments regarding `type(of:)` behaviour?

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [November 7, 2019, 2:31pm UTC](https://forums.swift.org/t/equality-of-functions/30295/53 "2019-11-07T14:31:18Z")

</div>

I am not and expert on the runtime implementation so I don’t have an informed opinion on your questions about runtime representation. That said, I do agree with your analysis of the expected behavior as a user.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 7, 2019, 5:45pm UTC](https://forums.swift.org/t/equality-of-functions/30295/54 "2019-11-07T17:45:24Z")

</div>

I would expect it to return some anonymous type. We probably shouldn't make any guarantees about what kind of type it produces.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 7, 2019, 5:54pm UTC](https://forums.swift.org/t/equality-of-functions/30295/55 "2019-11-07T17:54:56Z")

</div>

I was also thinking that a more incremental approach to this sort of thing might be, instead of introducing functions as a whole new kind of constraint, would be to allow the use of closure literals with protocols that look like function constraints, something like how Java lambdas work. If you have a protocol with a `callAsFunction` requirement, like:

```swift
protocol CallableWithInt {
  func callAsFunction(_: Int)
}

```

then, in a context that has a `CallableWithInt` constraint, we could allow you to use a closure literal as a value of an anonymous type conforming to the protocol, while also allowing synthesis of Equatable/Hashable/Comparable/Codable if the closure context values conform.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [November 7, 2019, 7:31pm UTC](https://forums.swift.org/t/equality-of-functions/30295/56 "2019-11-07T19:31:18Z")

</div>

> [@Joe\_Groff](#):
>
> we could allow you to use a closure literal as a value of an anonymous type conforming to the protocol, while also allowing synthesis of Equatable/Hashable/Comparable/Codable if the closure context values conform.

I like this idea! It's related to a more general idea I have been thinking about for providing syntactic sugar for anonymous structs. The idea is to use double braces `{{ }}` to denote an anonymous struct, a capture list to initialize properties, and support trailing anonymous types similar to how we support trailing closures.

When the protocol only has a single method (or possibly subscript) requirement, the body could be used to fulfill the requirement:

```swift
protocol Monoid {
    associatedtype Value
    var empty: Value
    func combine(_ lhs: Value, _ rhs: Value) -> Value
}
extension Sequence {
    func fold<M: Monoid>(_ monoid: M) -> Element
       where M.Value == Element
}
[1, 2, 3].fold {{ [empty = 0] in $0 + $1 }}

```

Ideally this could be made to work in cases such as `Monoid & Hashable` where memberwise-synthesizable conformances are assumed and the compiler understands that the single requirement being fulfilled is `combine`.

In cases where multiple requirements must be implemented manually, the body could also support explicit declarations:

```swift
[1, 2, 3].fold {{
   typealias Value = Int
   var empty: Int { 0 }
   func combine(_ lhs: Int, _ rhs: Int) -> Int { 
       lhs + hrs
   }
}}

```

To provide a concrete real world example applied to SwiftUI:

```swift
NavigationLink("Details") {{
    VStack {
        // details view content
    }
}}

```

I haven't thought much about whether that exact syntax is viable or not, but I think sugar along these lines is very interesting. Declaring a nominal type can be sometimes be inconvenient, especially considering the restriction on declaring them inside a function in generic contexts.

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 23, 2019, 3:06pm UTC](https://forums.swift.org/t/equality-of-functions/30295/57 "2019-11-23T15:06:51Z")

</div>

For my use cases having function types as structural and not requiring explicit naming is quite useful. Allowing only nominal function protocols to equatable would definitely decrease value of the feature, but we could live with that.

Also, I need support for generic function, which in this context, implies generic protocols, which Swift currently does not have. In combination with generic type alias syntax mentioned in [Improving the UI of generics](https://forums.swift.org/t/improving-the-ui-of-generics/22814), this may work, but it adds even more boilerplate code:

```
typealias CollectionOf<T> = Collection where Self.Element == T

protocol Predicate: Hashable {
    associatedtype Value
    func callAsFunction(_ value: Value) -> Bool
}
typealias PredicateOf<T> = Predicate where Self.Value == T

```

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 23, 2019, 3:18pm UTC](https://forums.swift.org/t/equality-of-functions/30295/58 "2019-11-23T15:18:46Z")

</div>

I've been thinking how exactly would I handle the need for declaring function types as nominal types. And assuming generic type aliases with constraints are available, I would probably just do this:

```
protocol Function0Protocol {
    associatedtype Result
    func callAsFunction() -> Result
}
typealias Function0<R> = Function0Protocol where Self.Result == R

protocol Function1Protocol {
    associatedtype Result
    associatedtype Arg0
    func callAsFunction(_ x0: Arg0) -> Result
}
typealias Function1<A0, R> = Function1Protocol where Self.Arg0 == A0, Self.Result == R

protocol Function2Protocol {
    associatedtype Result
    associatedtype Arg0
    associatedtype Arg1
    func callAsFunction(_ x0: Arg0, x1: Arg1) -> Result
}
typealias Function2<A0, A1, R> = Function2Protocol where Self.Arg0 == A0, Self.Arg1 == A1, Self.Result == R

...

```

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 23, 2019, 6:30pm UTC](https://forums.swift.org/t/equality-of-functions/30295/59 "2019-11-23T18:30:09Z")

</div>

> [@Nickolas\_Pohilets](#):
>
> Also, I need support for generic function, which in this context, implies generic protocols, which Swift currently does not have.

Generic protocols are unnecessary. A generic function could be modeled as a protocol with a generic `callAsFunction` requirement, which would in fact be something our structural function types don’t support today which protocols could.

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [November 23, 2019, 8:38pm UTC](https://forums.swift.org/t/equality-of-functions/30295/60 "2019-11-23T20:38:26Z")

</div>

If I understood you correctly, we are talking about two different things:

For the type `(T) -> Bool`, I'm talking about the case of:

```
struct Foo<T> {
    var f: (T) -> Bool
}

```

While you are talking about the case of:

```
struct Foo {
    var f: <T>(T) -> Bool
}

```

Generic function type != Type of the generic function

[Previous page](https://forums.swift.org/t/equality-of-functions/30295.md?page=2)

[Next page](https://forums.swift.org/t/equality-of-functions/30295.md?page=4)
