Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created January 9, 2018 07:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriseidhof/1b758b854ed72096490620a8d6128718 to your computer and use it in GitHub Desktop.
Save chriseidhof/1b758b854ed72096490620a8d6128718 to your computer and use it in GitHub Desktop.
Generic Show
enum Sum<A,B> {
case left(A)
case right(B)
}
struct Product<A,B> {
let a: A
let b: B
}
struct Iso<A,B> {
let to: (A) -> B
let from: (B) -> A
}
struct Unit { }
extension Unit: Show {
var text: String {
return ""
}
}
protocol Show {
var text: String { get }
}
extension Sum: Show where A: Show, B: Show {
var text: String {
switch self {
case .left(let a): return ".left(\(a.text)"
case .right(let b): return ".right(\(b.text)"
}
}
}
extension Product: Show where A: Show, B: Show {
var text: String {
return "(\(self.a), \(self.b))"
}
}
protocol Generic {
associatedtype Rep
var to: Rep { get }
}
struct Rec<A> where A: Generic {
let value: A
}
extension Rec: Show where A.Rep: Show {
var text: String {
return value.to.text
}
}
extension Array: Generic {
typealias Rep = Sum<Unit, Product<Element, Rec<Array<Element>>>>
var to: Sum<Unit, Product<Element, Rec<Array<Element>>>> {
if self.isEmpty { return .left(Unit()) }
return .right(Product(a: self[0], b: Rec(value: Array(self.suffix(from: 1)))))
}
}
extension Int: Show {
var text: String {
return "\(self)"
}
}
let arr = [1,2,3]
arr.to.text
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment