Skip to content

Instantly share code, notes, and snippets.

@sjoerdvisscher
Last active August 21, 2019 16:57
Show Gist options
  • Save sjoerdvisscher/12b3d5d0951e4399f125f5cf73d56beb to your computer and use it in GitHub Desktop.
Save sjoerdvisscher/12b3d5d0951e4399f125f5cf73d56beb to your computer and use it in GitHub Desktop.
Finally tagless in Swift 3
protocol Expr {
static func lit(_ x: Int) -> Self
static func add(_ lhs: Self, _ rhs: Self) -> Self
}
extension Int : Expr {
static func lit(_ x : Int) -> Int {
return x;
}
static func add(_ lhs: Int, _ rhs: Int) -> Int {
return lhs + rhs
}
}
extension String : Expr {
static func lit(_ x : Int) -> String {
return "\(x)";
}
static func add(_ lhs: String, _ rhs: String) -> String {
return "(\(lhs) + \(rhs))"
}
}
protocol Mul : Expr {
static func mul(_ lhs: Self, _ rhs: Self) -> Self
}
extension Int : Mul {
static func mul(_ lhs: Int, _ rhs: Int) -> Int {
return lhs * rhs
}
}
extension String : Mul {
static func mul(_ lhs: String, _ rhs: String) -> String {
return "(\(lhs) * \(rhs))"
}
}
extension Mul {
static var test: Self {
return add(lit(1), mul(lit(2), lit(3)))
}
}
print(Int.test) // 7
print(String.test) // (1 + (2 * 3))
func test2<A : Mul>() -> A {
return A.add(A.lit(1), A.mul(A.lit(2), A.lit(3)))
}
print(test2() as Int)
print(test2() as String)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment