Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Algebraic Data Type in Swift

Algebraic Data Type in Swift

Yasuhiro Inami

January 13, 2018
Tweet

More Decks by Yasuhiro Inami

Other Decks in Programming

Transcript

  1. Types in Swift Bool, Int, Int(N), UInt(N), Float, Double, String,

    Optional<T>, Array<T>, Set<T>, Dictionary<Key, Value>, etc... Value types can be expressed using struct and enum. struct Pair<A, B> { enum Either<A, B> { let a: A case a(A) let b: B case b(B) } }
  2. Algebraic Data Type (ADT) • Mathematics (algebra) just works in

    types • Algebra = study of mathematical symbols and the rules • e.g. • Abstract Algebra = study of "algebraic structures" • e.g. Magma, Semigroup, Monoid, Group, Ring, etc • Data and rules inside the data set • e.g. , ɹfor (Int, 0, )
  3. Question 1 ✨"✨ struct Pair<A, B> { let a: A

    let b: B } Are `Pair<A, B>` and `Pair<B, A>` the "same type"?
  4. Pair<A, B> == Pair<B, A> ? • No, they aren't

    the same ! (compiler distinguishes two) • But internal data types are almost identical • Only memory layout and function names (initializer, getter) are different • They are (categorically) isomorphic • Pair<A, B> Pair<B, A> • Mutual transformation exists
  5. Isomorphic Two objects cannot be distinguished ↓ There exists an

    "arrow" and also a unique "inverse arrow" ( 1:1 correspondence)
  6. /// From `Pair<A, B>` to `Pair<B, A>` func swapAB<A, B>(pair:

    Pair<A, B>) -> Pair<B, A> { return Pair<B, A>(a: pair.b, b: pair.a) } /// From `Pair<B, A>` to `Pair<A, B>` (inverse) func swapBA<B, A>(pair: Pair<B, A>) -> Pair<A, B> { return Pair<A, B>(a: pair.b, b: pair.a) } (Note: `swapAB` and `swapBA` are identical)
  7. Question 2 ✨"✨ struct Pair<A, B> { let a: A

    let b: B } struct A {} Are these two "isomorphic"?
  8. struct Pair<A, B> { let a: A let b: B

    } struct A {} ! Making `Pair<A, B>` from `A` seems impossible, so they must be different... ! But wait! `Pair<A, Void>` can be isomorphic to `A`!
  9. /// From `Pair<A, Void>` to `A` func getA<A>(pair: Pair<A, Void>)

    -> A { return pair.a } /// From `A` to `Pair<A, Void>` (inverse) func createPair<A>(a: A) -> Pair<A, Void> { return Pair<A, Void>(a: a, b: ()) } ! `Pair<A, Void>` and `A` are "isomorphic" "
  10. ! How about B = Int ? func getA<A>(pair: Pair<A,

    Int>) -> A { return pair.a } func createPair<A>(a: A) -> Pair<A, Int> { // ! Let's put any dummy value for `b` return Pair<A, Int>(a: a, b: 123) } ! No! `createPair(getA(pair)) pair`. `createPair` must be "unique" for corresponding `getA`.
  11. ! Then, how about B = Never ? func getA<A>(pair:

    Pair<A, Never>) -> A { return pair.a // can define } func createPair<A>(a: A) -> Pair<A, Never> { return Pair<A, Never>(a: a, b: /* can't define ☠ */) } ! There is no way to make `createPair` from `B = Never`...
  12. Question 3 ✨"✨ enum Either<A, B> { case a(A) case

    b(B) } Are `Either<A, B>` and `Either<B, A>` "isomorphic"?
  13. /// 1. From `Either<A, B>` to `Either<B, A>` /// 2.

    From `Either<B, A>` to `Either<A, B>` (inverse) func swap<A, B>(either: Either<A, B>) -> Either<B, A> { switch either { case let .a(a): return .b(a) case let .b(b): return .a(b) } } ! `Either<A, B>` and `Either<B, A>` are "isomorphic" "
  14. Question 4 ✨"✨ enum Either<A, B> { case a(A) case

    b(B) } struct A {} Are these two "isomorphic"?
  15. enum Either<A, B> { case a(A) case b(B) } struct

    A {} ! Now, it's easy to make `Either<A, B>` from `A`, but opposite seems difficult... ! But wait! `Either<A, Never>` can be isomorphic to `A`!
  16. /// From `A` to `Either<A, Never>` func createEither<A>(a: A) ->

    Either<A, Never> { return Either<A, Never>.a(a) } /// From `Either<A, Never>` to `A` (inverse) func getA<A>(either: Either<A, Never>) -> A { switch either { case let .a(a): return a case .b: fatalError("Never reaches here, !% safe") } } ! `Either<A, Never>` and `A` are "isomorphic" "
  17. ! How about B = Void ? /// From `A`

    to `Either<A, Void>` func createEither<A>(a: A) -> Either<A, Void> { return Either<A, Void>.a(a) } /// From `Either<A, Void>` to `A` (inverse) func getA<A>(either: Either<A, Void>) -> A { switch either { case let .a(a): return a case let .b(b): /* ! can't return `A` */ } }
  18. Characteristics of structand enum • struct ❤ Void • enum

    ❤ Never • " "What do we mean by ❤?" • Let's think categorically algebraically
  19. Think algebraically • struct is a product type • `struct

    Pair<A, B>` 㱻 • `Void` 㱻 • enum is a sum type • `enum Either<A, B>` 㱻 • `Never` 㱻
  20. • Pair<A, Void> A • • Either<A, Never> A •

    `Void` is `1` and `Never` is `0` in type-system world, and we can add (enum) and multiply (struct) just like elementary algebra ! " !
  21. Think more algebraically Elementary algebra: • Associativity: ɹ( = )

    • Distributivity: In type system: • ((A, B), C) (A, (B, C)) (A, B, C) • (A, Either<B, C>) Either<(A, B), (A, C)>
  22. List as recursive type indirect enum List<A> { case `nil`

    case cons(A, List<A>) } `List` can be expressed as .
  23. (continued) This represents infinite possible enum cases: enum List<A> {

    case element0 // 0 element case element1(A) // 1 element case element2(A, A) // 2 elements case element3(A, A, A) // 3 elements ... }
  24. Tree as recursive type indirect enum Tree<A> { case leaf

    case node(A, Tree<A>, Tree<A>) } `Tree` can be expressed as .
  25. Function as Exponential Object • `A -> B` can be

    expressed as • (Never -> A) Voidɹ㱻ɹ • (A -> Never) Neverɹ㱻ɹ ɹ( ) • (Void -> A) Aɹ㱻ɹ • (A -> Void) Voidɹ㱻ɹ
  26. Exponent Laws • • (C -> B -> A) ((B,

    C) -> A)ɹ/* currying ! */ • • (Either<B, C> -> A) (B -> A, C -> A) • • (C -> (A, B)) (C -> A, C -> B)
  27. Appendix 2: Derivative of ADT ...2 trees below the hole,

    and a list of "above node value (A)", "left or right side of the node subtree (Bool = 2)", "node subtree (Tree)".
  28. References • The Algebra of Algebraic Data Types, Part 1

    - Chris Taylor • The algebra (and calculus!) of algebraic data types • Understanding F-Algebras | Bartosz Milewski's Programming Cafe • ݍ࿦ษڧձ ୈ7ճ @ ϫʔΫεΞϓϦέʔγϣϯζ • Steve Awodey, Category Theory (2010)