Skip to content

Instantly share code, notes, and snippets.

@friedbrice
Forked from fghibellini/non-empty-pattern
Created March 11, 2019 00:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save friedbrice/ffb4cdde6688df3758577baf16489e04 to your computer and use it in GitHub Desktop.
Save friedbrice/ffb4cdde6688df3758577baf16489e04 to your computer and use it in GitHub Desktop.
-- | Can pattern match on nonempty lists
--
-- @
-- import Custom.NonEmpty (head, pattern NEL)
-- let arr = [1,2,3]
-- case arr of
-- NEL ne -> head ne
-- [] -> 42
-- @
--
-- This is an instance of [Explicitly-bidirectional pattern synonyms](https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms#Explicitly-bidirectionalpatternsynonyms).
-- It allows us to specify a pattern @NEL rs@ that can be used anywhere the @x:xs@ pattern is used, but instead of binding the two variables @x@ and @xs@ to the head and tail of the list,
-- it takes the head and tail and combines them into a `NonEmpty` instance that is then bound to the variable @rs@.
-- This is possible because x:xs and (x:|xs) are isomorphic.
-- The bidirectional pattern synonym works by defining the two directions of the isomorphism one on the right side of `<-` and one in the where clause.
-- The first (@(nonEmpty -> Just xs)@) relies on the [ViewPatterns extension](https://ghc.haskell.org/trac/ghc/wiki/ViewPatterns) that allows us to run an arbitrary
-- function to transform a @[a]@ into a @NonEmpty a@.
--
-- `ViewPatterns` breaks the pattern exhaustiveness checker of the compiler so we use the @COMPLETE@ pragma to tell GHC that if the user
-- pattern matches on @[]@ and @NEL xs@ then he has handled all the cases.
pattern NEL :: NonEmpty a -> [a]
pattern NEL xs <- (nonEmpty -> Just xs)
where NEL xs = toList xs
{-# COMPLETE [], NEL #-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment