Skip to content

Instantly share code, notes, and snippets.

@astanin
Last active December 19, 2015 21:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astanin/6019554 to your computer and use it in GitHub Desktop.
Save astanin/6019554 to your computer and use it in GitHub Desktop.
Generalizing `head`-like functions with TypeFamilies.
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}
module HasHead where
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as BSC
-- Usage example
--
-- ghci> (safeHead [], safeHead [1], safeHead (T.pack ""), safeHead (T.pack "foo"), safeHead (BSC.pack ""), safeHead (BSC.pack "bar"))
-- (Nothing,Just 1,Nothing,Just 'f',Nothing,Just 'b')
-- ghci>
--
class HasHead c where
type Element c :: *
safeHead :: c -> Maybe (Element c)
instance HasHead [a] where
type Element [a] = a
safeHead [] = Nothing
safeHead (x:_) = Just (x)
instance HasHead T.Text where
type Element T.Text = Char
safeHead t | T.null t = Nothing
| otherwise = Just (T.head t)
instance HasHead BSC.ByteString where
type Element BSC.ByteString = Char
safeHead s | BSC.null s = Nothing
| otherwise = Just (BSC.head s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment