/// The fixpoint of `Syntax`. /// /// `Syntax` is a non-recursive type parameterized by the type of its child nodes. Instantiating it to `Fix` makes it into a recursive tree by “tying the knot”—each child node of `Syntax` is represented by a `Fix` which in turn contains a `Syntax`. So in the same way that the `fix` function allows one to tie a non-recursive function into a recursive one, `Fix` allows one to tie a non-recursive type into a recursive one. Unfortunately, due to Swift’s lack of higher-rank types, this cannot currently be abstracted over the type which is made recursive, and thus it is hard-coded to `Syntax` rather than provided by a type parameter `F` applied to `Fix`. public enum Fix { /// A recursive instantiation of `Syntax`, unrolling another iteration of the recursive type. indirect case In(Syntax) public var out: Syntax { switch self { case let .In(s): return s } } } // MARK: - Equality extension Fix { public static func equals(param: (A, A) -> Bool)(_ left: Fix, _ right: Fix) -> Bool { return Syntax.equals(ifLeaf: param, ifRecur: equals(param))(left.out, right.out) } } public func == (left: Fix, right: Fix) -> Bool { return Fix.equals(==)(left, right) } // MARK: - Hashing extension Fix { public func hash(param: A -> Hash) -> Hash { return out.hash(ifLeaf: param, ifRecur: { $0.hash(param) }) } } extension Fix where A: Hashable { var hash: Hash { return hash(Hash.init) } }