Decodable Randomness: Part 2

Episode #32 • Oct 1, 2018 • Subscriber-Only

This week we compare our Decodable solution to building random structures with a composable solution involving the Gen type, exploring the differences and trade-offs of each approach. Along the way we’ll rediscover a familiar old friend with a brand new application.

Decodable Randomness: Part 2
Introduction
00:05
Composing structure
01:00
Zipping structure
11:45
Strengthening structure
16:10
Strengthening structure again
19:52
What’s the point?
22:26

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

So what we are seeing is that we put in a lot of upfront work with Decodable, and got some impressive results out it because we can effortlessly generate a random value from pretty much any data type we define. However, the system is very rigid and will mostly create invalid values for your domain, like email addresses and positive user ids.

Maybe there’s another way. We saw last time that our Gen type was able to do things that the Swift 4.2 randomness APIs were not capable of, so maybe it can help us out again?

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

Exercises

  1. Redefine Gen‘s base unit of randomness, random, which is a Gen<UInt32> to work with Swift 4.2’s base unit of randomness, the RandomNumberGenerator protocol. The base random type should should change to UInt64.

  2. Swift 4.2’s protocol-oriented solution allows us to define custom types that conform to RandomNumberGenerator. Update Gen to evaluate given any RandomNumberGenerator by changing run’s signature.

  3. Use a custom random number generator that can be configured with a stable seed to allow for the Gen type to predictably generate the same random value for a given seed.

    You can look to Nate Cook’s playground, shared on the Swift forums, or (for bonus points), you can define your own linear congruential generator (or LCG).

  4. Write a helper that runs a property test for XCTest! A property test, given a generator and a block of code, will evaluate the block of code with a configurable number of random runs. If the block returns true, the property test passes. It it returns false, it fails. The signature should be the following.

    func forAll<A>(_ a: Gen<A>, propertyShouldHold: (A) -> Bool)
    

    It should, internally, call an XCTAssert function. Upon failure, print out the seed so that it can be reproduced.

  5. Enhance the forAll API to take file: StaticString = #file, line: UInt = #line, which can be passed to XCTest in order to highlight the correct line on failure.

Downloads