Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Cocoa
- precedencegroup PipeOperatorPrecedence {
- associativity: left
- higherThan: LogicalConjunctionPrecedence
- }
- infix operator |>: PipeOperatorPrecedence
- public func |> <A, B>(arg: A,
- f: @escaping (A) -> B) -> B {
- return f(arg)
- }
- precedencegroup KleisliOperatorPrecedence {
- associativity: left
- higherThan: PipeOperatorPrecedence
- }
- infix operator >=>: KleisliOperatorPrecedence
- public enum Result<T, E> {
- case ok(T)
- case error(E)
- }
- extension Result {
- public func bind<B>(_ f: @escaping (T) -> Result<B, E>) -> Result<B, E> {
- switch self {
- case .ok(let x):
- return f(x)
- case .error(let e):
- return Result<B, E>.error(e)
- }
- }
- }
- public func >=> <A, B, C, E>(f: @escaping (A) -> Result<B, E>,
- g: @escaping (B) -> Result<C, E>) -> (A)->Result<C, E> {
- return { a in
- f(a).bind(g)
- }
- }
- struct UserInput {
- let email: String
- let password: String
- }
- struct User {
- let id = UUID.init()
- let email: String
- }
- extension User: CustomDebugStringConvertible {
- var debugDescription: String {
- return "{ id: \(id), email: \(email) }"
- }
- }
- enum UserError: Error {
- case invalidEmail, invalidPassword, alreadyExist
- case unknown(cause: Error)
- }
- //key-value as DB store
- var usersDb = [String: User]()
- //simulate DB runtime error
- enum DbError: Error {
- case duplicateKeyError
- }
- func saveToDb(_ input: UserInput) throws -> User {
- if usersDb[input.email] != nil {
- print("user \(input.email) already exists")
- throw DbError.duplicateKeyError
- }
- let newUser = User(email: input.email)
- usersDb[input.email] = newUser
- print("user saved: \(newUser)")
- return newUser
- }
- func validateEmail(input: UserInput) -> Result<UserInput, UserError> {
- //Simple regular expression for email validation
- let emailPredicate = NSPredicate(format: "SELF MATCHES %@", "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
- //Validate email
- return emailPredicate.evaluate(with: input.email) ? .ok(input) : .error(UserError.invalidEmail)
- }
- func validatePassword(input: UserInput) -> Result<UserInput, UserError> {
- return input.password.count > 6 ? .ok(input) : .error(UserError.invalidPassword)
- }
- func saveToDbWithResult(input: UserInput) -> Result<User, UserError> {
- do {
- let user = try saveToDb(input)
- return .ok(user)
- } catch DbError.duplicateKeyError {
- return .error(UserError.alreadyExist)
- } catch {
- return .error(UserError.unknown(cause: error))
- }
- }
- func register(input: UserInput) -> Result<User, UserError> {
- return validateEmail(input: input)
- .bind(validatePassword)
- .bind(saveToDbWithResult)
- }
- func registerOperators(input: UserInput) -> Result<User, UserError> {
- return input
- |> validateEmail
- >=> validatePassword
- >=> saveToDbWithResult
- }
- let test1 = UserInput(email: "123@mail.com", password: "password")
- let registrationResult = register(input: test1)
- switch registrationResult {
- case .ok(let user):
- print("user \(user) successfully registered")
- case .error(let error):
- print("failed to register new user. Error: \(error)")
- }
Add Comment
Please, Sign In to add comment