Credits to the great wonderful amazing Daniel Vebman for introducing me to the topic
Indirect Enums are the most functional of types. For this entry, I will be assuming you have already or are currently taking 3110.
Let's get into things!
Ever wanted to make natural numbers in Swift? Neither have I, but here's how to do it.
As a quick refresher, here's the OCaml version:
type Nat =|Zero|Succ of Nat
Hopefully, this rings a bell. 3 would be Succ (Succ (Succ Zero)).
In Swift, ideally you could do:
enumNat {case zerocase succ(Nat)}
Sadly, this does not compile: "Recursive enum 'Nat' is not marked 'indirect'".
A little look into what's going on here: types like enums and structs require that memory size is known at compile time. With recursion, it has no clue what the size is. As it suggests, we can use the keyword indirect to circumvent this:
Both of the above Nat's are valid. Making an entire enum indirect makes all of the cases indirect, but you can also make individual cases indirect. Alright, well let's start building this thing out!
First, let's create some functions to help us create and analyze Nats:
var value: Int {get {switch self {case .zero:return0caselet .succ(sub):return1+ sub.count } }}staticfuncfromInt(_int: Int) -> Nat {assert(int >=0)if int ==0 {return .zero } else {return .succ(fromInt(int -1)) }}
Time to test!
for i in0...100 {assert(i == Nat.fromInt(i).count)}// And one morelet x: Nat = .succ(.succ(.succ(.zero)))assert(x.count==3)
Great those passed! Let's work on adding some operators. I'll start off with an important one for code: ++ that Swift happens to lack: