Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

As a "half way" point, modern (21+) java brings pattern matching switch statements to the language, but you'd probably construct the F# version in Java using a sealed "marker" interface. Something like

    sealed interface Result permits ValidationError, SearchQuery, UserProfile {}
Along with the specific implementations of those ValidationError, SearchQuery and UserProfile classes and then a switch statement like:

    Result res = db.query(input);
    return switch(res) {
      case ValidationError ve -> context.renderError(ve);
      case SearchQuery sq -> context.redirect("Search", Map.of("q", sq));
      case UserProfile up -> context.redirect("Profile", Map.of("user", up));
    };
The sealed interface gives you compile time checks that your switch statement is exhaustive wherever you use it.

Before that pattern matching, I might have used a Function<Context, R> instead in the Result interface. This is off the top of my head without the benefit of an IDE telling me if I've done a stupid with the generics and type erasure but something like:

    interface Result<R> {
      public R handleWithContext(Context c);
    }

    class ValidationError<RenderedError> {
      public RenderedError handleWithContext(Context c) {
        return c.renderError(this);
      }
    }

    class SearchQuery<Redirect> {
      public Redirect handleWithContext(Context c) {
        return c.redirect("Search", Map.of("q", this);
      }
    }
etc. In either case though I think you're right that an empty interface is something that should be examined closer.




Sealed interface doesn’t look bad for some use cases. I wish C# had it too.



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

Search: