A new Swift video series exploring functional programming and more.
#32 • Monday Oct 1, 2018 • Subscriber-only

Decodable Randomness: Part 2

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.

#32 • Monday Oct 1, 2018 • Subscriber-only

Decodable Randomness: Part 2

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.


Subscribe to Point‑Free

This episode is for subscribers only. To access it, and all past and future episodes, become a subscriber today!

See subscription optionsorLog in

Sign up for our weekly newsletter to be notified of new episodes, and unlock access to any subscriber-only episode of your choosing!

Sign up for free episode

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?

Subscribe to Point-Free

👋 Hey there! Does this episode sound interesting? Well, then you may want to subscribe so that you get access to this episodes and more!


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.

Chapters
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