{-# LANGUAGE DeriveDataTypeable #-} -- | Nonempty lists. module Agda.Utils.NonemptyList ( module Agda.Utils.NonemptyList , toList ) where import Control.Monad import Data.Data (Data) import Data.Foldable (Foldable, toList) import Data.Traversable (Traversable) import Data.Semigroup import qualified Data.List as List infixr 5 :! data NonemptyList a = (:!) { headNe :: a, tailNe :: [a] } deriving (Eq, Ord, Functor, Foldable, Traversable, Data) instance Semigroup (NonemptyList a) where (x :! xs) <> (y :! ys) = x :! xs ++ y : ys instance Applicative NonemptyList where pure x = x :! [] (<*>) = ap instance Monad NonemptyList where return = pure (x :! xs) >>= f = foldr1 (<>) (f x : map f xs) instance Show a => Show (NonemptyList a) where showsPrec _ = showList . toList -- | Returns the union of the argument lists seen as sets. The order of the -- elements in the result is not specified. Precondition: arguments contain -- no duplicates. unionNe :: Eq a => NonemptyList a -> NonemptyList a -> NonemptyList a unionNe (x :! xs) (y :! ys) = z :! zs where z : zs = List.union (x : xs) (y : ys) -- | Zip two nonempty lists. zipWithNe :: (a -> b -> c) -> NonemptyList a -> NonemptyList b -> NonemptyList c zipWithNe f (x :! xs) (y :! ys) = f x y :! zipWith f xs ys -- | Zip two nonempty lists. zipNe :: NonemptyList a -> NonemptyList b -> NonemptyList (a, b) zipNe = zipWithNe (,) -- | Case on a list, getting a nonempty list in the cons case. caseListNe :: [a] -> b -> (NonemptyList a -> b) -> b caseListNe [] e ne = e caseListNe (x : xs) e ne = ne (x :! xs) -- | Case on a list, with list last. listCaseNe :: b -> (NonemptyList a -> b) -> [a] -> b listCaseNe e ne xs = caseListNe xs e ne -- | Check if an element is present in a list. elemNe :: Eq a => a -> NonemptyList a -> Bool elemNe y (x :! xs) = elem y (x : xs)