(s, a) -> s • Mealy Machine • Transition function (s, a) -> s • Output function (s, a) -> b • Moore Machine • Transition function (s, a) -> s • Output function s -> b
(s, a) -> s • Mealy Machine • Transition function (s, a) -> s • Output function (s, a) -> b • Moore Machine • Transition function (s, a) -> s • Output function s -> b design pattern for state machines
maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of N. Ex: 9 = 1001 → 2 Started Zero One Binary Gap
registerRoot case profileRegister case startWithMercari case emailLogin case atteLogin case home } enum RegistrationEvent: Hashable { case showRegisterRoot(loginMode: RootViewController.LoginMode?) case registerWithFacebook(profile: FacebookProfile?) case startWithMercari(resource: MercariIdResource?, tokenPair: TokenPair?, showsCloseButton: Bool) case loginWithEmail(showsCancelButton: Bool) case loginWithAtte(resource: MercariIdResource?, tokenPair: TokenPair?) case loginAndShowHome(tokenPair: TokenPair?, userId: Int64, hasMercariItem: Bool) }
not use default value for associated value in enum • Proposal: SE-0155 Accepted status but not included in Swift 4 struct DefaultEvent { static let showRegisterRoot: RegistrationEvent = .showRegisterRoot() static let registerWithFacebook: RegistrationEvent = .registerWithFacebook(profile: nil) static let startWithMercari: RegistrationEvent = .startWithMercari(resource: nil, token: nil) static let loginWithEmail: RegistrationEvent = .loginWithEmail() static let loginWithAtte: RegistrationEvent = .loginWithAtte(resource: nil, token: nil) static let loginAndShowHome: RegistrationEvent = .loginAndShowHome(token: nil, userId: 0) }
function (s, a) -> s • Mealy Machine • Transition function (s, a) -> s • Output function (s, a) -> b • Moore Machine • Transition function (s, a) -> s • Output function s -> b
some state and returns a value along with some new state: s -> (s, a) class State<S, A> { private let run: (S) -> (S, A) init(f: @escaping (S) -> (S, A)) { self.run = f } func run(s: S) -> (S, A) { return self.run(s) } }
B) -> State<S, B> { return State<S, B> { s in let (s1, val) = self.run(s: s) return (s1, g(val)) } } func flatMap<B>(g: @escaping (A) -> State<S, B>) -> State<S, B> { return State<S, B> { s in let (s1, val) = self.run(s: s) return g(val).run(s: s1) } } } A stateful computation is a function that takes some state and returns a value along with some new state: s -> (s, a)
root case registerRoot case profileRegister case startWithMercari case emailLogin case atteLogin case home } enum REvent { case showRegisterRoot case registerWithFacebook(profile: FacebookProfile) case startWithMercari(resource: MercariIdResource, token: String) case loginWithEmail case loginWithAtte(resource: MercariIdResource, token: String) case loginAndShowHome(token: String, userId: Int64) } custom type
{ event in switch event { case .registerWithFacebook(let profile): let vc = ProfileRegisterViewController.make(withDependency: .init(facebookProfile: profile)) return State<RState, UIViewController> { s in let s1: RState = s == .registerRoot ? .profileRegister : .any return (s1, vc) //... } } let registrationMachine = MonadicAutomaton<RState, REvent, UIViewController>(f : transitionFunc) A S B A S B