I had a real use-case for the never
function in an application the other day. This was all a bit complicated so jump to the bottom of the post if you just want to see the code that uses never
. Otherwise, here’s some buildup on how I got to the point of using never
Generic pages
I wanted to write some generic layout functions that could render any page in my application. In addition to chrome and navigation, the layout would also handle displaying notifications and modal content.
The state of each page was modeled using dramatically varying types. In addition, pages could define modals that only existed on that page, but I wanted them to be displayed in the layout just like the other modals. To handle this situation, I created a type that looked like this:
type alias Page content modal =
{ notificationQueue : NotificationQueue
, modal : Modal modal
, content : content
, -- more shared fields
}
type Modal local
= Global GlobalModal
| LocalModal local
| ModalClosed
Specific pages
These generic types allowed me to vary all the page-specific stuff. For example I might have something like:
initialModel : Page LocalContent LocalModal
initialModel =
-- build up a `Page` record
type alias LocalContent = { field1 : String, field2 : Int, ... }
type LocalModal = Modal1 | Modal2
Layout
Finally I created a function that could render any Page
in a layout. Two important things it needs to know are:
- How do you render your page-specific content?
- How do you render your page-specific modal content?
viewPage :
{ viewContent : content -> List (Html a)
, viewModal : modal -> Html a
}
-> Page content modal
-> Html a
This might look like:
view : Page LocalContent LocalModal -> Html Msg
view page =
Generic.viewPage
{ viewContent = viewLocalContent
, viewModal = viewLocalModal
}
page
Never
This all worked fine until I created a page that didn’t have any local modals. I figured out that I could have a page type like Page LocalContent Never
but what should I pass as the viewModal
function?
I could pass a lambda like this but that felt very kludgy:
(\modal -> text "this will never get called")
Eventually I realized that the never
function was my solution:
view : Page LocalContent Never -> Html Msg
view page =
Generic.viewPage
{ viewContent = viewLocalContent
, viewModal = never
}
page