Slide 1

Slide 1 text

"ͶΔ" ͸͍͍ͧ 2018.12.9 #shinjukult @to4iki 1

Slide 2

Slide 2 text

Me • @to4iki •  • AbemaTV • builderscon 2

Slide 3

Slide 3 text

ಥવͰ͕͢ɺ ഑ྻૢ࡞ʹؔͯ͠ɺ 3

Slide 4

Slide 4 text

e.g. 1 if xs.isEmpty { // fallback processing. } else { // anything. } 4

Slide 5

Slide 5 text

e.g. 1 guard !xs.isEmpty else { fatalError("unrechable.") } // anything 5

Slide 6

Slide 6 text

e.g. 2 /// GraphQL type’s fields enum UserField: String { case id, name, email } /// build up a query func query(_ fields: Set) -> String { return (["{\n"] + fields.map { " \($0.rawValue)\n" } + ["}\n"]) .joined() } 6

Slide 7

Slide 7 text

e.g. 2 ! request success query([.id, .name]) // { // name // id // } ! request runtime-error query([]) // { // } 7

Slide 8

Slide 8 text

! • ֓೦ϨϕϧͰ Nil or Cons(ଘࡏ͢Δ͔) Λҙࣝ͢Δඞཁ͕͋Δ • ܕ҆શͰ͸ͳ͍ ! 8

Slide 9

Slide 9 text

ۭ഑ྻͱ͍͏ɺ ಉ͡഑ྻͳΜ͚ͩͲ ͦͷঢ়ଶ(ཁૉ͕༗Δ͔ແ͍͔)Λ ҙࣝ͠ͳ͍ͱ͍͚ͳ͍ 9

Slide 10

Slide 10 text

ۭͱ͍͏ঢ়ଶ͕ى͜Γ͑ͳ͍ ഑ྻ͕͋Ε͹Α͍ͷͰ͸ 10

Slide 11

Slide 11 text

Nel(ͶΔ) 11

Slide 12

Slide 12 text

Non Empty List 12

Slide 13

Slide 13 text

NonEmptyList2 /// a data type which represents a non empty list of A. /// single element (head) and optional structure (tail). struct NonEmptyArray { let head(T) let tail: [T] } 2 Swift͸ඪ४ܕͰList͕ଘࡏ͠ͳ͍ͷͰɺArrayΛࣄྫʹͯ͠ѻ͏ 13

Slide 14

Slide 14 text

! // [1, 2, 3] NonEmptyArray(head: 1, tail: [2, 3]) 14

Slide 15

Slide 15 text

other solution enum NonEmptyArray { case single(T) indirect case cons(T, NonEmptyArray) } // [1, 2, 3] NonEmptyArray.cons(1, .cons(2, .single(3))) 15

Slide 16

Slide 16 text

ۭͷঢ়ଶΛදݱͰ͖Δͷ͸Array ͚ͩͰ͸ͳ͍ΑͶ 16

Slide 17

Slide 17 text

NonEmpty struct NonEmpty { var head: C.Element var tail: C init(_ head: C.Element, _ tail: C) { self.head = head self.tail = tail } } 17

Slide 18

Slide 18 text

typealias NonEmptyArray = NonEmpty> typealias NonEmptySet = NonEmpty> where T: Hashable typealias NonEmptyDictionary = NonEmpty> where K: Hashable // etc... 18

Slide 19

Slide 19 text

NonEmpty Λඪ४ͷίϨΫγϣϯૢ࡞ʹ͚͍ۙͮͯ͘ 19

Slide 20

Slide 20 text

(ུ) 20

Slide 21

Slide 21 text

! overload non-nil property extension NonEmpty { /// overload non-nil var first: C.Element { return self.head } } extension NonEmpty where C: BidirectionalCollection { /// overload non-nil var last: C.Element { return self.tail.last ?? self.head } } 21

Slide 22

Slide 22 text

Array let xs = [1, 2, 3] xs.first.map { $0 + 1 } ?? 0 xs.last! + 1 // unsafe ! NonEmptyArray let xs = NonEmptyArray(1, 2, 3) xs.first + 1 xs.last + 1 22

Slide 23

Slide 23 text

Demo 23

Slide 24

Slide 24 text

Other lang • Haskel: Data.List.NonEmpty • https://hackage.haskell.org/package/semigroups-0.16.0.1/docs/Data-List- NonEmpty.html • Elm: List.Nonempty • https://package.elm-lang.org/packages/mgold/elm-nonempty-list/3.1.0/List- Nonempty • scalaz / cats • functional java • etc... 24

Slide 25

Slide 25 text

Advanced 25

Slide 26

Slide 26 text

Validation(Nel) • Monad • Applicative Functor • https://typelevel.org/cats/datatypes/validated.html /// `Result` with success-value, `nel` as the failure type. enum Validated { case valid(Value) case invalid(NonEmptyArray) } 26

Slide 27

Slide 27 text

Kotlin: arrow.Validated • https://arrow-kt.io/docs/datatypes/validated/ @higherkind sealed class Validated : ValidatedOf { data class Valid(val a: A) : Validated() data class Invalid(val e: E) : Validated() } 27

Slide 28

Slide 28 text

e.g let validatedPassword: Validated ... switch validatedPassword { case .valid(let value): print(value) case .invalid(let errors): // e.g. preset `errors.first` messages } 28

Slide 29

Slide 29 text

Conclusion • Ϧετ͸ ۭ or ۭͰ͸ͳ͍ͷ 2छྨͷঢ়ଶ͕ଘࡏ͢Δ • NonEmpty ʹΑΓɺܕϨϕϧͰ ۭͰ͸ͳ͍ ঢ়ଶΛ୲อ͢Δ͜ͱ͕Ͱ͖Δ • ڊਓͷݞ(ଟݴޠͰͷ࣮૷ྫ)ʹ৐͍ͬͯ͜͏ 29

Slide 30

Slide 30 text

SeeAlso • https://www.pointfree.co/episodes/ep20-nonempty • http://eed3si9n.com/learning-scalaz/ja/Validation.html • http://xuwei-k.github.io/scalaz-docs/validation.html 30

Slide 31

Slide 31 text

Thanks 31