Search code examples
elmunion-types

Elm union subsets


Say I have a union type like this:

type Route
  = Home
  | License
  | UserProfile { username : String }
  | Search { query : String }
  | SomeOtherPage

In practice I frequently need to work with subsets of this union. For example:

type StaticRoute = Home | License

I would like to be able to define functions which accept subsets like the above, instead of the wider Route.

I don't want to nest StaticRoute inside of Route, like so:

type Route
  = Static StaticRoute
  | UserProfile { username : String }
  | Search { query : String }
  | SomeOtherPage

This is because I want to be able to define many different subsets of Route, some of which could overlap:

type StaticRoute = Home | License
type RouteWithServerRendering = Home | Search { query : String }
type LoggedInRoute = SomeOtherPage
-- and so on…

How then can I define subsets of Route without repeating definitions?


Solution

  • Jasper Woudenberg recently posted Conversion functions, five stars , which advocates for having similar types and using conversion functions to translate between one type to another.

    In your case, it might look like this:

    module Route exposing (fromStaticRoute, toStaticRoute)
    
    fromStaticRoute : StaticRoute -> Route
    fromStaticRoute staticRoute =
        case staticRoute of
            Static.Home ->
                Home
            Static.License ->
                License
    
    toStaticRoute : Route -> Maybe StaticRoute
    toStaticRoute route =
        case route of
            Home ->
                Just Static.Home
            License ->
                Just Static.License
            _ ->
                Nothing