Skip to content

Instantly share code, notes, and snippets.

@MarcSteven
Forked from chriseidhof/AppDelegate.swift
Created December 14, 2015 01:18
Show Gist options
  • Save MarcSteven/442c417933f62da4ae46 to your computer and use it in GitHub Desktop.
Save MarcSteven/442c417933f62da4ae46 to your computer and use it in GitHub Desktop.
Functional Swift Talk
import UIKit
struct Screen<A> {
let run: (A -> ()) -> UIViewController
}
struct Step<A> {
let build: (navigationController: UINavigationController, callback: A -> ()) -> UIViewController
}
extension Step {
init(_ screen: Screen<A>) {
build = { navigationController, callback in
let vc = screen.run(callback)
navigationController.pushViewController(vc, animated: true)
return vc
}
}
func run(callback: A -> ()) -> UIViewController {
let nc = UINavigationController()
build(navigationController: nc, callback: callback)
return nc
}
func flatMap<B>(f: A -> Step<B>) -> Step<B> {
return Step<B>(build: { (navigationController, callback) -> UIViewController in
self.build(navigationController: navigationController, callback: { a in
f(a).build(navigationController: navigationController, callback: callback)
})
})
}
}
func question(text: String) -> Step<Int> {
return Step(question(text))
}
func question(text: String) -> Screen<Int> {
return Screen { callback in
let storyBoard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let vc = storyBoard.instantiateViewControllerWithIdentifier("MyViewController") as! ViewController
_ = vc.view // Force loading of the view
vc.textLabel.text = text
vc.onComplete = callback
return vc
}
}
class Game {
let randomNumber: Int = Int(arc4random_uniform(100))
var numberOfGuessesLeft = 3
func turn(guess: Int) -> Step<Int> {
numberOfGuessesLeft--
if guess == randomNumber {
return question("You won!")
} else if numberOfGuessesLeft == 0 {
return question("You lost! The number was \(randomNumber)")
} else {
let hint = "The number was \(randomNumber > guess ? "larger" : "smaller")."
return question("\(hint) Wrong answer, try again. \(numberOfGuessesLeft) guesses left").flatMap(turn)
}
}
func startGame() -> UIViewController {
return question("Guess a number between 0 and 100").flatMap(turn).run { _ in () }
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window?.rootViewController = Game().startGame()
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment