Guest User

Untitled

a guest
Dec 3rd, 2018
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.03 KB | None | 0 0
  1. import Cocoa
  2.  
  3. precedencegroup PipeOperatorPrecedence {
  4. associativity: left
  5. higherThan: LogicalConjunctionPrecedence
  6. }
  7.  
  8. infix operator |>: PipeOperatorPrecedence
  9.  
  10. public func |> <A, B>(arg: A,
  11. f: @escaping (A) -> B) -> B {
  12. return f(arg)
  13. }
  14.  
  15. precedencegroup KleisliOperatorPrecedence {
  16. associativity: left
  17. higherThan: PipeOperatorPrecedence
  18. }
  19.  
  20. infix operator >=>: KleisliOperatorPrecedence
  21.  
  22. public enum Result<T, E> {
  23. case ok(T)
  24. case error(E)
  25. }
  26.  
  27. extension Result {
  28. public func bind<B>(_ f: @escaping (T) -> Result<B, E>) -> Result<B, E> {
  29. switch self {
  30. case .ok(let x):
  31. return f(x)
  32. case .error(let e):
  33. return Result<B, E>.error(e)
  34. }
  35. }
  36. }
  37.  
  38. public func >=> <A, B, C, E>(f: @escaping (A) -> Result<B, E>,
  39. g: @escaping (B) -> Result<C, E>) -> (A)->Result<C, E> {
  40. return { a in
  41. f(a).bind(g)
  42. }
  43. }
  44.  
  45.  
  46. struct UserInput {
  47. let email: String
  48. let password: String
  49. }
  50.  
  51. struct User {
  52. let id = UUID.init()
  53. let email: String
  54. }
  55.  
  56. extension User: CustomDebugStringConvertible {
  57. var debugDescription: String {
  58. return "{ id: \(id), email: \(email) }"
  59. }
  60. }
  61.  
  62. enum UserError: Error {
  63. case invalidEmail, invalidPassword, alreadyExist
  64. case unknown(cause: Error)
  65. }
  66.  
  67. //key-value as DB store
  68. var usersDb = [String: User]()
  69.  
  70. //simulate DB runtime error
  71. enum DbError: Error {
  72. case duplicateKeyError
  73. }
  74.  
  75. func saveToDb(_ input: UserInput) throws -> User {
  76. if usersDb[input.email] != nil {
  77. print("user \(input.email) already exists")
  78. throw DbError.duplicateKeyError
  79. }
  80. let newUser = User(email: input.email)
  81. usersDb[input.email] = newUser
  82. print("user saved: \(newUser)")
  83. return newUser
  84. }
  85.  
  86. func validateEmail(input: UserInput) -> Result<UserInput, UserError> {
  87. //Simple regular expression for email validation
  88. let emailPredicate = NSPredicate(format: "SELF MATCHES %@", "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
  89. //Validate email
  90. return emailPredicate.evaluate(with: input.email) ? .ok(input) : .error(UserError.invalidEmail)
  91. }
  92.  
  93. func validatePassword(input: UserInput) -> Result<UserInput, UserError> {
  94. return input.password.count > 6 ? .ok(input) : .error(UserError.invalidPassword)
  95. }
  96.  
  97. func saveToDbWithResult(input: UserInput) -> Result<User, UserError> {
  98. do {
  99. let user = try saveToDb(input)
  100. return .ok(user)
  101. } catch DbError.duplicateKeyError {
  102. return .error(UserError.alreadyExist)
  103. } catch {
  104. return .error(UserError.unknown(cause: error))
  105. }
  106. }
  107.  
  108. func register(input: UserInput) -> Result<User, UserError> {
  109. return validateEmail(input: input)
  110. .bind(validatePassword)
  111. .bind(saveToDbWithResult)
  112. }
  113.  
  114. func registerOperators(input: UserInput) -> Result<User, UserError> {
  115. return input
  116. |> validateEmail
  117. >=> validatePassword
  118. >=> saveToDbWithResult
  119. }
  120.  
  121. let test1 = UserInput(email: "123@mail.com", password: "password")
  122. let registrationResult = register(input: test1)
  123. switch registrationResult {
  124. case .ok(let user):
  125. print("user \(user) successfully registered")
  126. case .error(let error):
  127. print("failed to register new user. Error: \(error)")
  128. }
Add Comment
Please, Sign In to add comment