2015-01-27 16:46:20 +03:00
|
|
|
-- | Extra list functions and list-like types.
|
|
|
|
module Data.List.Extra where
|
|
|
|
|
2015-07-21 18:09:11 +03:00
|
|
|
import Control.Applicative ((<$>), (<*>))
|
2015-01-27 16:46:20 +03:00
|
|
|
import Control.DeepSeq (NFData(..))
|
2015-07-21 18:09:11 +03:00
|
|
|
import Data.Foldable (Foldable(..))
|
|
|
|
import Data.Traversable (Traversable(..), fmapDefault, foldMapDefault)
|
2015-01-27 16:46:20 +03:00
|
|
|
|
|
|
|
-- * Regular lists
|
|
|
|
|
2015-01-30 18:16:15 +03:00
|
|
|
-- | Check if a list has more than some number of elements.
|
|
|
|
moreThan :: [a] -> Int -> Bool
|
|
|
|
moreThan [] n = n < 0
|
|
|
|
moreThan _ 0 = True
|
|
|
|
moreThan (_:xs) n = moreThan xs (n-1)
|
|
|
|
|
2015-01-27 16:46:20 +03:00
|
|
|
-- * Non-empty lists
|
2015-02-01 04:21:42 +03:00
|
|
|
|
|
|
|
-- This gets exposed to users of the library, so it has a bunch of
|
2015-01-27 16:46:20 +03:00
|
|
|
-- classes which aren't actually used in the rest of the code to make
|
|
|
|
-- it more friendly to further use.
|
|
|
|
|
|
|
|
-- | The type of non-empty lists.
|
|
|
|
data NonEmpty a = a :| [a] deriving (Eq, Ord, Read, Show)
|
|
|
|
|
|
|
|
instance Functor NonEmpty where
|
2015-07-21 18:09:11 +03:00
|
|
|
fmap = fmapDefault
|
|
|
|
|
|
|
|
instance Foldable NonEmpty where
|
|
|
|
foldMap = foldMapDefault
|
|
|
|
|
|
|
|
instance Traversable NonEmpty where
|
|
|
|
traverse f (a:|as) = (:|) <$> f a <*> traverse f as
|
2015-01-27 16:46:20 +03:00
|
|
|
|
|
|
|
instance NFData a => NFData (NonEmpty a) where
|
|
|
|
rnf (x:|xs) = rnf (x, xs)
|
|
|
|
|
|
|
|
-- | Convert a 'NonEmpty' to a regular non-empty list.
|
|
|
|
toList :: NonEmpty a -> [a]
|
|
|
|
toList (a :| as) = a : as
|
2015-07-20 20:42:19 +03:00
|
|
|
|
|
|
|
-- | Convert a regular non-empty list to a 'NonEmpty'. This is
|
|
|
|
-- necessarily partial.
|
|
|
|
unsafeToNonEmpty :: [a] -> NonEmpty a
|
|
|
|
unsafeToNonEmpty (a:as) = a :| as
|
|
|
|
unsafeToNonEmpty [] = error "Cannot convert [] to NonEmpty!"
|