Slide 1

Slide 1 text

Refinement types github.com/hectr

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

refinement types a.k.a encoding valida,ons at the typelevel github.com/hectr

Slide 4

Slide 4 text

Why? github.com/hectr

Slide 5

Slide 5 text

Stringly typed example struct Foo: Codable { let id: String } • id cannot be nil ! • id could be empty " github.com/hectr

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

The idea is not new: make illegal states unrepresentable github.com/hectr

Slide 10

Slide 10 text

Refinement types implementa.ons: (frameworks or dialects) • Scala • Haskell • TypeScript • Perl • ... github.com/hectr

Slide 11

Slide 11 text

What about Swi,? github.com/hectr

Slide 12

Slide 12 text

There isn't language support for refinement types. ! github.com/hectr

Slide 13

Slide 13 text

There isn't language support for refinement types (yet). ! github.com/hectr

Slide 14

Slide 14 text

But... github.com/hectr

Slide 15

Slide 15 text

refined type = base type + predicate github.com/hectr

Slide 16

Slide 16 text

refined type ≈ wrapper type + generic constraint github.com/hectr

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

wrapper type + generic constraint protocol Predicate { associatedtype Value static func isValid(value: Value) -> Bool } github.com/hectr

Slide 19

Slide 19 text

Refined string example (cont) struct Not: 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

Slide 20

Slide 20 text

Refined string example (cont) let foo: Refined> github.com/hectr

Slide 21

Slide 21 text

Refined string example (cont) let foo: Refined> ! github.com/hectr

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Is it that easy? github.com/hectr

Slide 25

Slide 25 text

No, it is not... github.com/hectr

Slide 26

Slide 26 text

Refined types need to seamlessly integrate with their base types. github.com/hectr

Slide 27

Slide 27 text

type transparency github.com/hectr

Slide 28

Slide 28 text

type transparency struct Photo: Codable { var title: Refined>> var height: Refined> var width: Refined> } 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

Slide 29

Slide 29 text

But that is another story... github.com/hectr

Slide 30

Slide 30 text

github.com/hectr

Slide 31

Slide 31 text

github.com/hectr

Slide 32

Slide 32 text

github.com/hectr

Slide 33

Slide 33 text

github.com/refined-swi4 github.com/hectr