Hacker News new | past | comments | ask | show | jobs | submit login

>I just wish go had proper sum types.

It's by far my favorite feature of Swift.

Enums + Payloads + switches are incredibly simple yet so effective. You can make a simple state object, isolate it with an actor, then stream it anywhere with Combine (or now Observability). You'll get full compiler safety too, forcing any new state to be handled everywhere.

You can even stack that with _generic_ payloads that conform to protocols, and if you're feel brave you can make those payloads equable completions for _typed returns_.

for example (I hate formatting on here, but I'll give it a shot)

// A user state enum that conforms to loggable.

// The state is generic, any object T that conforms to "Partner" protocol can be a partner

enum UserState<T: Partner>: Loggable {

   // Your states
   case loggedOut(error: String?)
   case loggingIn(email: Email)   // Email type is a string that's been validated
   case loggedIn(authToken: String, user: User, partner: T)
   case loggingOut(exampleBlock: (String) -> Bool) // You can embed a callback here
   

   // Utility Functions

   /// Is the user logged in?
   func isLoggedIn() -> Bool {
      switch self { 
         case .loggedOut, .loggingIn: return false
         case .loggedIn: return true
      }
   } 

   /// Loggable conformance
   func logText() -> String {
    // switch that converts state into something that's safe for your logging service
   }
}

In the above, any subscriber that gets a UserState object can switch on it, and for example if you're logged in you 100% get the auth token, user, etc. It's impossible to be logged in without those in-context.

It might look something like this in your UI:

/// Called by a subscriber that's hooked in to the state stream

func onUserStateChanged(newState: UserState) {

   switch newState {

      case let .loggedOut:
      // Impossible? Error UI

      case let .loggingIn, .loggingOut:
      // loading UI

      case let .loggedIn(authToken: _, user: user, parner: partner):
      // set some text "hello \(user.userName)"
      // display an image: \(MyRemoteLoader.url(url: partner.primaryLogoURL))
      // Button to website: Button(url: partner.homePageURL)
   }
}

add a new state later? The compiler will error in the 500 places in your codebase you didn't handle the new case with one build command.




Love this. Not only is it my favorite feature of swift, but I often say swift enums are my favorite feature of any programming language. They are just so elegant and powerful




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: