Swift generics and specialization - swift

I realize Swift generics are not like C++ templates where the code is specialized and generated at instantiation, but is there a way to get the following code to specialize the second call?
func X1<R>(i: R) {
print("R")
}
func X1(i: Int) {
print("Int")
}
func X2<R>(i: R) {
X1(i: i)
}
X2(i: "s")
X2(i: 1)
X1(i: "s")
X1(i: 1)
In particular, the output I see is:
R
R
R
Int
But I really want the X2 call to X1 for Int to specialize to the X1 Int:
R
Int
R
Int
I know I can do it by creating another X2 with Int as the type, but I was hoping to avoid that.
EDIT A few of the answers suggests adding handling per specialized type (i.e., add a func X2(i: Int) or doing type casting let x = i as? Int) -- that's what I'm trying to avoid as there could be a lot of specialized types, for example:
func X1(i: Double) {
print("Double")
}
func X1(i: Bool) {
print("Bool")
}
func X1(i: Float) {
print("Float")
}

You can try to cast R in X2:
func X2<R>(i: R) {
if let x = i as? Int {
X1(i: x)
} else {
X1(i: i)
}
}
This will force a call to the Int version of X1. As the compiler will specialize the generics away, all of the casting will probably go away.
Depending on the situation you might be able to use protocol extensions with associated type constraints to solve this problem.

I only make it work by specialising X2 for Int type:
func X1<R>(i: R) {
print("Any")
}
func X1(i: Int) {
print("Int")
}
func X2<R>(i: R) {
X1(i: i)
}
func X2(i: Int) {
X1(i: i)
}
X2(i: "s")
X2(i: 1)
X1(i: "s")
X1(i: 1)

Related

Swift function that swaps two values

I need to write a function that swaps the contents of any two variables. This is what I have currently but I am getting the error "Cannot assign to value: 'a' is a 'let' constant".
func swap<T>(a: T, b: T) {
(a, b) = (b, a);
}
Can somebody please explain why this doesn't work and suggest how to fix it?
Thank you.
You need to make the parameters inout to be able to do that, like this:
func swap<T>(_ a: inout T,_ b: inout T) {
(a, b) = (b, a)
}
var a = 0, b = 1
swap(&a, &b)
The parameters inside your function is immutable so it cannot be swapped , like if you trying to swap two let value:
let x = 5
let y = 6
//if you try to swap these values Xcode will tell you to change their declaration to var
Here almost the same and to be able to change the values you have to pass inout declaration like below :
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
// call it like this
var x = 1
var y = 2
swapTwoValues(&x, &y)
// Note that you cannot call it like this: swapTwoValues(&1, &2)
That is because the arguments of functions are constants and are treated as local properties, unless you mark them inout and then they are treated as sort of "pass-through" properties that aren't confined to the scope of the function.
var kiwi = "kiwi"
var mango = "mango"
func swap<T>(a: inout T, b: inout T) {
(a, b) = (b, a)
}
swap(&kiwi, &mango)
If having to put & everywhere or the verbosity of the function annoy you, you could always use a descriptive operator like this:
infix operator <->: AssignmentPrecedence
func <-> <A>(lhs: inout A, rhs: inout A) {
(lhs, rhs) = (rhs, lhs)
}
var kenobi = "Hello there!"
var helloThere = "Kenobi..."
helloThere <-> kenobi
print(helloThere, kenobi, separator: "\n")
// Hello there!
// Kenobi...
Which I feel looks much nicer. You don't need to use & in operators with inout parameters – that's how the += and -= operators work:
public extension AdditiveArithmetic {
static func +=(lhs: inout Self, rhs: Self) {
lhs = lhs + rhs
}
static func -=(lhs: inout Self, rhs: Self) {
lhs = lhs - rhs
}
}

Extended capability for a more restrictive generic

I have a generic binary search tree based on Comparable:
public class BSTree<T: Comparable> {
public func insert(_ val: T, _ n: Int) {
// ...
}
#discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
// ...
}
}
I want to add the ability to provide the sum of the values, if T is an arithmetic type. I tried the following:
public class BSTree<T: Comparable> {
private var sumStorage: T?
public func insert(_ val: T, _ n: Int) {
if let arithVal = val as? AdditiveArithmetic {
for _ in 0 ..< n { sumStorage += arithVal }
}
// ...
}
#discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
// ...
numDeleted = ...
if let arithVal = val as? AdditiveArithmetic {
for _ in 0 ..< numDeleted { sumStorage -= arithVal }
}
}
}
extension BSTree where T: AdditiveArithmetic {
public var sum: T {
sumStorage as? T ?? T.zero
}
}
Of course, when I try to cast val as AdditiveArithmetic I get “Protocol 'AdditiveArithmetic' can only be used as a generic constraint because it has Self or associated type requirements”. Plus sumStorage isn’t AdditiveArithmetic, so I can’t add to it, and I can’t make it a stored property of the extension, because ... you just can’t.
What I finally came up with was to use inheritance:
class SummedBSTree<T>: BSTree<T> where T: AdditiveArithmetic & Comparable {
public var sum = T.zero
override public func insert(_ val: T, _ n: Int) {
super.insert(val, n)
for _ in 0 ..< n { sum += val }
}
#discardableResult
override public func delete(_ val: T, _ n: Int) -> Int {
let numDeleted = super.delete(val, n)
for _ in 0 ..< numDeleted { sum -= val }
return numDeleted
}
}
This works, but it seems like it’s a case of using a sledgehammer where a jeweler’s screwdriver should be able to do the trick. It’s frustrating that something that would be so easy to do in Objective-C (and other less strongly typed languages) is so difficult in Swift. Can someone come up with a way of adding the summing capability without subclassing?
import UIKit
//https://stackoverflow.com/questions/61784548/swift-extended-capability-for-a-more-restrictive-generic
protocol ON1Speedable {
associatedtype Item: Comparable
var sumStorage: Item? { get set }
}
public class BSTree<T: Comparable> {
var sumStorage: T?
init(sumStorage: T? = nil) {
self.sumStorage = sumStorage
}
}
extension ON1Speedable where Item: AdditiveArithmetic, Item: Strideable, Item.Stride: SignedInteger {
mutating func insert(_ val: Item, _ n: Int) {
sumStorage = sumStorage ?? Item.zero
for _ in 0..<n { sumStorage! += val }
}
#discardableResult
mutating func delete(_ val: Item, _ n: Int) -> Item? {
sumStorage = sumStorage ?? Item.zero
for _ in Item.zero..<val { sumStorage! -= val }
return sumStorage
}
}
extension BSTree: ON1Speedable { }
var g2 = BSTree<Int>(sumStorage: 0)
g2.sumStorage
g2.insert(5, 5)
g2.sumStorage // 25
g2.delete(5, 5) // 0
var g3 = BSTree<String>()
g3.sumStorage // nil
//g3.insert("foo", 5) // Error: Referencing instance method 'insert' on 'ON1Speedable' requires that 'String.Stride' conform to 'SignedInteger'
g3.sumStorage // nil
//g3.delete("bar", 5) // Error: Referencing instance method 'delete' on 'ON1Speedable' requires that 'String.Stride' conform to 'SignedInteger'

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.

Method with generic type parameter inside Swift extension

While trying to implement a simple lazy list in Swift, I tried creating an extension for enum in Swift, with a generic method inside (emulating a type class-like behavior, as I'm trying out Swift while being a Scala developer most of the time), like so:
enum LazyList<A>{
case Elem(x: A, xs: () -> LazyList<A>)
case Nil()
}
extension LazyList {
func map<B>(f: (A) -> B) -> LazyList<B> {
func lazyMap(l: LazyList<A>, lf: (A) -> B) -> LazyList<B> {
switch l {
case let .Elem(e, es):
return LazyList.Elem(x: lf(e), xs: {() -> LazyList<B> in return lazyMap(es(), lf: lf)})
case .Nil:
return LazyList.Nil()
}
}
return lazyMap(self, lf: f)
}
}
This however does not run in the playground, failing to compile with error below:
error: cannot convert value of type 'LazyList<A>' to expected argument type 'LazyList<_>'
return LazyList.Elem(x: lf(e), xs: {() -> LazyList<B> in return lazyMap(es(), lf: lf)})
How can I get it to compile? Is it because the compiler cannot infer the return type of lazyMap?
simply remove the "LazyList." from your switch cases :)
enum LazyList<A>{
case Elem(x: A, xs: () -> LazyList<A>)
case Nil()
}
extension LazyList {
func map<B>(f: (A) -> B) -> LazyList<B> {
func lazyMap(l: LazyList<A>, lf: (A) -> B) -> LazyList<B> {
switch l {
case let .Elem(e, es):
return .Elem(x: lf(e), xs: {() -> LazyList<B> in return lazyMap(es(), lf: lf)})
case .Nil:
return .Nil()
}
}
return lazyMap(self, lf: f)
}
}

Is there any way to determine sub-protocol conformance for instance conforming to generic protocol in Swift 2 (at runtime or during compilation)?

I'm porting Java library to Swift 2.0 and have some troubles with generics.
I have following protocol hierarchy:
public protocol Graph {
typealias V: Hashable
typealias E: Hashable
func getAllEdges(sourceVertex: V, targetVertex: V) -> Set<E>?
func getEdge(sourceVertex: V, targetVertex: V) -> E?
func getEdgeFactory() -> EdgeFactory<V, E>?
func addEdge(sourceVertex: V, targetVertex: V) -> E?
func addEdge(sourceVertex: V, targetVertex: V, e: E) -> Bool
func addVertex(v: V) -> Bool
func containsEdge(sourceVertex: V, targetVertex: V) -> Bool
func containsEdge(e: E) -> Bool
func containsVertex(v: V) -> Bool
func edgeSet() -> Set<E>
func edgesOf(v: V) -> Set<E>
func removeAllEdges<T: CollectionType where T.Generator.Element == E>(edges: T) -> Bool
func removeAllEdges(sourceVertex: V, targetVertex: V) -> Set<E>?
func removeAllVertices<T: CollectionType where T.Generator.Element == V>(vertices: T) -> Bool
func removeEdge(sourceVertex: V, targetVertex: V)
func removeEdge(e: E) -> Bool
func removeVertex(v: V) -> Bool
func vertexSet() -> Set<V>
func getEdgeSource(e: E) -> V
func getEdgeTarget(e: E) -> V
func getEdgeWeight(e: E) -> Double
}
public protocol DirectedGraph: Graph {
func inDegreeOf(vertex: V) -> Int
func incomingEdgesOf(vertex: V) -> Set<E>
func outDegreeOf(vertex: V) -> Int
func outgoingEdgesOf(vertex: V) -> Set<E>
}
public protocol UndirectedGraph: Graph {
func degreeOf(vertex: V) -> Int
}
And here's definition of class which causes trouble:
public class CrossComponentIterator
<V: Hashable, E: Hashable, D, G: Graph
where G.V == V, G.E == E>
: AbstractGraphIterator<V, E>
Namely, it has method which should init one of its variables based on actual type of graph passed - DirectedGraph or UndirectedGraph.
I've tried solving this by declaring multiple versions of the function which does this:
func createGraphSpecifics<DG: Graph where DG: DirectedGraph, DG.V == V, DG.E == E>(graph: DG)
-> CrossComponentIteratorSpecifics<V, E>
{
return DirectedSpecifics<V, E, DG>(graph: graph)
}
func createGraphSpecifics<UG: Graph where UG: UndirectedGraph, UG.V == V, UG.E == E>(graph: UG)
-> CrossComponentIteratorSpecifics<V, E>
{
return UndirectedSpecifics<V, E, UG>(graph: graph)
}
func createGraphSpecifics<GG: Graph where GG.V == V, GG.E == E>(graph: GG)
-> CrossComponentIteratorSpecifics<V, E>
{
fatalError("Unknown graph type instance")
}
But unfortunately, only last version of function is called for any instance of graph (even if it conforms to "DirectedGraph" or "UndirectedGraph")
And I know, that probably I can solve this problem by converting protocols DirectedGraph and UndirectedGraph to abstract classes
(by that I mean classes with fatalError() in each declared function since Swift doesn't support abstract classes de jure).
But maybe there is another, more elegant and Swifty solution?
In Java this is trivial - conformance to interface is checked at runtime:
if (g instanceof DirectedGraph<?, ?>) {
return new DirectedSpecifics<V, E>((DirectedGraph<V, E>) g);
} else {
return new UndirectedSpecifics<V, E>(g);
}
Edit here's minimal code for what I'm trying to achieve:
protocol P {
// This typealias makes impossible to use 'P'
// (or its descendants) as a type.
// It can be used only as generic constraint.
typealias A
// myfunc is needed for compiler to infer 'A'
func myfunc(a: A)
}
protocol P1:P {
func p1specific(a: A)
}
protocol P2:P {
func p2specific(a: A)
}
struct S<T:P> {
init(t: T) {
// TODO: check if 't' conforms to 'P1', 'P2', both or neither
}
}
// Examples of concrete implementations of 'P1' and 'P2'
struct S1<X>:P1{
func myfunc(a: X) {}
func p1specific(a: X) {}
}
struct S2<X>:P2{
func myfunc(a: X) {}
func p2specific(a: X) {}
}
Is there any way to determine sub-protocol conformance for instance
conforming to generic protocol in Swift 2 (at runtime or during
compilation)?
Yes.
Here's my trick for achieving type erasure, hence allowing one to utilize the runtime. Observe _P:
protocol _P {
static var _A: Any.Type { get }
func _myfunc(_a: Any) -> Void?
}
extension _P where Self: P {
static var _A: Any.Type {
return A.self
}
func _myfunc(_a: Any) -> Void? {
return (_a as? A).map(myfunc)
}
}
protocol P {
typealias A
func myfunc(a: A)
}
protocol _P1:_P {
func _p1specific(_a: Any) -> Void?
}
extension _P1 where Self: P1 {
func _p1specific(_a: Any) -> Void? {
return (_a as? A).map(p1specific)
}
}
protocol P1:_P1, P {
func p1specific(a: A)
}
protocol _P2:_P {
func _p2specific(_a: Any) -> Void?
}
extension _P2 where Self: P2 {
func _p2specific(_a: Any) -> Void? {
return (_a as? A).map(p2specific)
}
}
protocol P2:_P2, P {
func p2specific(a: A)
}
You can now determine whether a value conforms to P1 or P2, and force cast accordingly. Additionally, the generic parameter A is now available via the opaque Any.Type.
(x as? _P1) != nil ? true : false
import XCPlayground
import Foundation
protocol P {}
protocol P1:P {}
protocol P2:P {}
struct S1:P1{}
struct S2:P2{}
struct S<T:P> {
var p1: P1?
var p2: P2?
init(t: T) {
p1 = t as? P1
p2 = t as? P2
}
}
let p1 = S1()
let p2 = S2()
let s1 = S(t: p1)
let s2 = S(t: p2)
dump(s1)
dump(s2)
/*
▿ S<S1>
▿ p1: S1
- Some: S1
- p2: nil
▿ S<S2>
- p1: nil
▿ p2: S2
- Some: S2
*/
use
g is Type // trur or false
and
let v2 = v1 as? Type // v2 = v2 or nil
in swift
update
protocol P {
typealias A
}
protocol P1:P {}
protocol P2:P {}
struct S1:P1{
typealias A = Int
}
struct S2:P2{
typealias A = Double
}
struct S<T:P> {
var p1: S1?
var p2: S2?
init(t: T) {
p1 = t as? S1
p2 = t as? S2
}
}
let p1 = S1()
let p2 = S2()
let s1 = S(t: p1)
let s2 = S(t: p2)
.....
protocol P {
// This typealias makes impossible to use 'P'
// (or its descendants) as a type.
// It can be used only as generic constraint.
typealias A
// myfunc is needed for compiler to infer 'A'
func myfunc(a: A)
}
protocol P1:P {}
protocol P2:P {}
// aka 'abstract' conforming to P1
struct S1:P1{
typealias A = AnyObject
func myfunc(a: A) {}
}
// aka 'abstract' conforming to P2
struct S2:P2{
typealias A = Int
func myfunc(a: A) {}
}
// generic struct with type conforming to P
struct S<T:P> {
init(t: T) {
// TODO: check if 't' conforms to 'P1', 'P2', both or neither
if t is S1 {
print("t conforms to P1, because it is type S1")
}
if t is S2 {
print("t conforms to P2, besause it is type S2")
}
}
}
let s1 = S(t: S1()) // t conforms to P1, because it is type S1
let s2 = S(t: S2()) // t conforms to P2, besause it is type S2
// WARNING !!!!!!
// var s = s1
// s = s2 // error: cannot assign value of type 'S<S2>' to type 'S<S1>'