From f4e462eba2b9398c1cc6b5b68138c77d90045e6f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 16 Oct 2015 16:05:37 -0400 Subject: [PATCH] =?UTF-8?q?Cofree=20uses=20Memo=20to=20ensure=20that=20sta?= =?UTF-8?q?tefully-computed=20subtrees=20are=20=E2=80=9Cok.=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Randomness is an effect. --- prototype/Doubt/Cofree.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/prototype/Doubt/Cofree.swift b/prototype/Doubt/Cofree.swift index 862e401cf..678e89e7d 100644 --- a/prototype/Doubt/Cofree.swift +++ b/prototype/Doubt/Cofree.swift @@ -4,18 +4,18 @@ /// /// This type is dual to `Free`. Where `Free` is inhabited by syntax trees where some terms are replaced with `B`s, `Cofree` is inhabited by syntax trees where all terms are annotated with `B`s. In Doubt, this allows us to e.g. annotate terms with source range information, categorization, etc. public enum Cofree { - case Unroll(B, () -> Syntax) + case Unroll(B, Memo>) public var unwrap: Syntax { switch self { case let .Unroll(_, rest): - return rest() + return rest.value } } public init(_ annotation: B, @autoclosure(escaping) _ syntax: () -> Syntax) { - self = .Unroll(annotation, syntax) + self = .Unroll(annotation, Memo(unevaluated: syntax)) } @@ -25,7 +25,7 @@ public enum Cofree { /// /// As this is the dual of `Free.iterate`, it’s unsurprising that we have a similar guarantee: coiteration is linear in the size of the constructed tree. public static func coiterate(annotate: B -> Syntax)(_ seed: B) -> Cofree { - return .Unroll(seed, { annotate(seed).map(coiterate(annotate)) }) + return .Unroll(seed, Memo { annotate(seed).map(coiterate(annotate)) }) } } @@ -43,7 +43,7 @@ extension Cofree: CustomDebugStringConvertible { extension Cofree { public func map(transform: B -> Other) -> Cofree { - return .Unroll(transform(extract), { self.unwrap.map { $0.map(transform) } }) + return .Unroll(transform(extract), Memo { self.unwrap.map { $0.map(transform) } }) } } @@ -61,7 +61,7 @@ extension Cofree { /// Returns a new `Cofree` by recursively applying `transform` to each node, producing the annotations for the copy. public func extend(transform: Cofree -> Other) -> Cofree { - return .Unroll(transform(self), { self.unwrap.map { $0.extend(transform) } }) + return .Unroll(transform(self), Memo { self.unwrap.map { $0.extend(transform) } }) } /// Returns a new `Cofree` constructed by recursively annotating each subtree with itself. @@ -112,4 +112,5 @@ extension Cofree where B: Categorizable { } +import Memo import Prelude