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

Algebraic Data Type in Swift

Algebraic Data Type in Swift

Eac0bf787b5279aca5e699ece096956e?s=128

Yasuhiro Inami

January 13, 2018
Tweet

Transcript

  1. Algebraic Data Type in Swift ɹɹɹɹɹɹɹɹɹ 2018/01/13 Tokyo iOS Meetup

    Yasuhiro Inami / @inamiy
  2. None
  3. 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) } }
  4. 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, )
  5. Question 1 ✨"✨ struct Pair<A, B> { let a: A

    let b: B } Are `Pair<A, B>` and `Pair<B, A>` the "same type"?
  6. 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
  7. Isomorphic Two objects cannot be distinguished ↓ There exists an

    "arrow" and also a unique "inverse arrow" ( 1:1 correspondence)
  8. None
  9. /// 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)
  10. Question 2 ✨"✨ struct Pair<A, B> { let a: A

    let b: B } struct A {} Are these two "isomorphic"?
  11. 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`!
  12. /// 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" "
  13. ! 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`.
  14. ! 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`...
  15. Pair<A, B> Pair<B, A> Pair<A, Void> A Pair<Void, A> A

    struct ❤ Void
  16. Question 3 ✨"✨ enum Either<A, B> { case a(A) case

    b(B) } Are `Either<A, B>` and `Either<B, A>` "isomorphic"?
  17. /// 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" "
  18. Question 4 ✨"✨ enum Either<A, B> { case a(A) case

    b(B) } struct A {} Are these two "isomorphic"?
  19. 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`!
  20. /// 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" "
  21. ! 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` */ } }
  22. Either<A, B> Either<B, A> Either<A, Never> A Either<Never, A> A

    enum ❤ Never
  23. Characteristics of structand enum • struct ❤ Void • enum

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

    Pair<A, B>` 㱻 • `Void` 㱻 • enum is a sum type • `enum Either<A, B>` 㱻 • `Never` 㱻
  25. • 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 ! " !
  26. 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)>
  27. List as recursive type indirect enum List<A> { case `nil`

    case cons(A, List<A>) } `List` can be expressed as .
  28. (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 ... }
  29. Tree as recursive type indirect enum Tree<A> { case leaf

    case node(A, Tree<A>, Tree<A>) } `Tree` can be expressed as .
  30. (continued1) 1 The Algebra of Algebraic Data Types, Part 2

    - Chris Taylor
  31. Function as Exponential Object • `A -> B` can be

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

    C) -> A)ɹ/* currying ! */ • • (Either<B, C> -> A) (B -> A, C -> A) • • (C -> (A, B)) (C -> A, C -> B)
  33. Algebraic Data Type = and for types!

  34. Appendix 1: Initial Algebra ADT as fixed point of endofunctor

    (initial algebra): e.g.
  35. 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)".
  36. 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)
  37. Thanks! Yasuhiro Inami @inamiy