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
Related
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
}
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
}
}
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)
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>'
I'm trying to implement generic broadcasting function for each type that supports specific protocol. For example:
protocol Proto {
typealias ItemType
typealias Callback = (Self, ItemType)
func register(tag: String, cb: Callback)
func unregister(tag: String)
}
class Foo : Proto {
typealias ItemType = Int
func register(tag: String, cb: (Foo, Int)) {
}
func unregister(tag: String) {
}
}
func bc <T: Proto> (p: T, value: T.ItemType, os: [String: T.Callback]) {
for (k, v) in os {
v(p, value) // error: cannot invoke v with argument list of...
}
}
Question is how to implement bc function right?
i think swift is buggy at this place. maybe you can use
protocol Proto {
typealias ItemType
func register(tag: String, cb: (Self, Self.ItemType)->())
func unregister(tag: String, cb: (Self, Self.ItemType)->())
}
class Foo : Proto {
func register(tag: String, cb: (Foo, Int)->()) {
}
func unregister(tag: String, cb: (Foo, Int)->()) {
}
}
func bc <T: Proto> (p: T, value: T.ItemType, os: [String : (T,T.ItemType)->()]) {
for (_, vc) in os {
vc(p, value) // error: cannot invoke v with argument list of...
}
}