Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created April 27, 2018 09:40
Show Gist options
  • Save chriseidhof/fb0a2a081579277e297a335dfa37dfb3 to your computer and use it in GitHub Desktop.
Save chriseidhof/fb0a2a081579277e297a335dfa37dfb3 to your computer and use it in GitHub Desktop.
enum Command {
case buttonTapped
case textChanged(String)
}
enum SideEffect<C> {
case anEvent(C)
case readFile((String) -> C)
// ...
}
// We can't get Codable for SideEffect because the associated value is a function.
// Instead, we can defunctionalize: replace every function parameter with a value. First of all, a protocol that says: I can construct commands from that still need a String parameter:
protocol ConstructFromString {
associatedtype FromString
static func construct(_ d: FromString, _ s: String) -> Self
}
// Now for every enum constructor that still takes a string, we add a case to the `FromString` enum, and switch over it in `construct`
extension Command: ConstructFromString {
enum FromString {
case textChanged // you have one case for each (String) -> Command
}
static func construct(_ d: FromString, _ s: String) -> Command {
switch d {
case .textChanged: return .textChanged(s)
}
}
}
// Now we replace our `SideEffect` implementation with one that allows you to construct SideEffects from Strings.
enum SideEffectAlt<C: ConstructFromString> {
case anEvent(C)
case readFile(C.FromString)
}
extension SideEffectAlt: Codable where C: Codable, C.FromString: Codable {
// todo
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment