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

Refinement types

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