-
-
Save benlings/b52843a85633044a4411 to your computer and use it in GitHub Desktop.
Object-Oriented Programming in Functional Programming in Swift - now with Open Recursion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on http://www.sicpers.info/2015/05/object-oriented-programming-in-functional-programming-in-swift/ | |
// Each method now has an extra `self` parameter | |
struct List<T> { | |
let count: List<T> -> () -> Int | |
let at: List<T> -> Int -> T? | |
} | |
// Helper functions to pass self to the self parameter | |
func lCount<T>(l: List<T>) -> Int { | |
return l.count(l)() | |
} | |
func lAt<T>(l: List<T>)(_ idx: Int) -> T? { | |
return l.at(l)(idx) | |
} | |
func EmptyList<T>() -> List<T> | |
{ | |
return List( | |
count: { s in { 0 } }, | |
at: { s in { _ in nil } } | |
) | |
} | |
func LinkedList<T>(head:T, tail:List<T>) -> List<T> | |
{ | |
return List( | |
count: { s in { 1 + lCount(tail) } }, | |
at: { s in { index in (index == 0) ? head : lAt(tail)(index - 1) } } | |
) | |
} | |
// Step Six: Inherit from objects | |
// Changed references to super's methods to be super's type because otherwise | |
// we can't call super's methods on ourself | |
struct ListWithDescription<T> { | |
let list: List<T> | |
let describe: ListWithDescription<T> -> () -> String | |
} | |
// Overrides of helper functions for the subclass | |
func lAt<T>(l: ListWithDescription<T>) -> Int -> T? { | |
return lAt(l.list) | |
} | |
func lCount<T>(l: ListWithDescription<T>) -> Int { | |
return lCount(l.list) | |
} | |
// Helper function for new subclass method | |
func lDescribe<T>(l: ListWithDescription<T>) -> String { | |
return l.describe(l)() | |
} | |
func ListOfStringsWithDescription(proto: List<String>) -> | |
ListWithDescription<String> | |
{ | |
let describe: ListWithDescription<String> -> () -> String = { s in | |
{ | |
var output = "" | |
for i in 0..<lCount(s) { | |
output = output.stringByAppendingString(lAt(s)(i)!) | |
output = output.stringByAppendingString(" ") | |
} | |
return | |
output.stringByTrimmingCharactersInSet( | |
NSCharacterSet.whitespaceCharacterSet() | |
) | |
} | |
} | |
// I've in-lined SubtypeListByAddingDescription | |
return ListWithDescription<String>( | |
list: proto, | |
describe: describe | |
) | |
} | |
let awesomeGreeting = | |
ListOfStringsWithDescription(LinkedList("Hello,", | |
LinkedList("World", | |
EmptyList()))) | |
lAt(awesomeGreeting) //"World" | |
lDescribe(awesomeGreeting) //"Hello, World" | |
// Step 7 override base class method that subclass uses | |
// Override `at` method | |
func ListOfStringWithDescriptionWithPrefix(proto: ListWithDescription<String>, prefix: String) -> ListWithDescription<String> | |
{ | |
return ListWithDescription<String>( | |
list: List<String>( | |
count: proto.list.count, | |
at: { s in | |
{ idx in lAt(proto)(idx).map { "\(prefix) \($0)" } } | |
} | |
), | |
describe: proto.describe | |
) | |
} | |
// `describe` method uses overriden `at` method | |
let superAwesomeGreeting = ListOfStringWithDescriptionWithPrefix(awesomeGreeting, "yo") | |
lDescribe(superAwesomeGreeting) // "yo Hello, yo World" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment