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

Refinement types

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for hectr hectr
March 21, 2019

Refinement types

Refinement types for Swift

Avatar for hectr

hectr

March 21, 2019
Tweet

Other Decks in Programming

Transcript

  1. a refinement type is a type endowed with a predicate

    which is assumed to hold for any element of the refined type. — Wikipedia github.com/hectr
  2. Stringly typed example struct Foo: Codable { let id: String

    } • id cannot be nil ! • id could be empty " github.com/hectr
  3. Refined string example struct Foo: Codable { let id: String.NonEmpty

    } • id cannot be nil ! • id cannot be empty " github.com/hectr
  4. Refined string example struct Foo: Codable { let id: String.NonEmpty

    } • id cannot be nil ! • id cannot be empty " ... we'll explain this later. github.com/hectr
  5. Almost any type is suscep0ble to be refined: • Int

    (e.g. divisible by...) • Float (greater than...) • Double, etc.: (e.g. nega7ve) • String: (e.g. starts with...) • Array (e.g. contains...) • Set (e.g. count is...) github.com/hectr
  6. wrapper type + generic constraint struct Refined<Constraint: Predicate> { let

    wrapped: Constraint.Value init?(_ value: Constraint.Value) { guard Constraint.isValid(value: value) else { return nil } self.wrapped = value } } github.com/hectr
  7. wrapper type + generic constraint protocol Predicate { associatedtype Value

    static func isValid(value: Value) -> Bool } github.com/hectr
  8. Refined string example (cont) struct Not<P: Predicate>: Predicate { static

    func isValid(value: P.Value) -> Bool { return !P.isValid(value: value) } } struct IsEmpty: Predicate { static func isValid(value: String) -> Bool { return value.isEmpty } } github.com/hectr
  9. Refined string example (cont) // let foo: Refined<Not<IsEmpty>> extension String

    { typealias Empty = Refined<IsEmpty> typealias NonEmpty = Refined<Not<IsEmpty>> } github.com/hectr
  10. Refined string example (cont) // let foo: Refined<Not<IsEmpty>> extension String

    { typealias Empty = Refined<IsEmpty> typealias NonEmpty = Refined<Not<IsEmpty>> } let foo: String.NonEmpty github.com/hectr
  11. type transparency struct Photo: Codable { var title: Refined<Count<String, LessThan<Int_20>>>

    var height: Refined<RangeOf<Double_100, Double_1000>> var width: Refined<RangeOf<Double_100, Double_1000>> } let jsonString = "{\"width\":150,\"height\":150,\"title\":\"Apple\"}" let jsonData = jsonString.data(using: .utf8)! let photo = try! JSONDecoder().decode(Photo.self, from: jsonData) _ = photo.width * 2.0 _ = "photo called " + photo.title XCTAssertEqual(photo.title, "Apple") XCTAssertEqual(photo.width, 150) github.com/hectr