module Data.List.NonEmpty(
NonEmpty,
neHead,
neTail,
nonEmpty,
(|:),
toNonEmpty,
toNonEmpty',
unsafeToNonEmpty,
(.:),
reverse,
scanl,
scanl1,
scanr,
scanr1,
iterate,
cycle,
inits,
tails,
sort,
insert,
unzip
) where
import Control.Applicative
import Control.Monad
import Control.Comonad
import Control.Functor.Pointed
import Control.Functor.Zip
import Control.Arrow
import Data.Foldable
import Data.Maybe
import Data.Traversable
import Data.Typeable (Typeable)
import Data.Data (Data)
import Data.Semigroup
import qualified Data.List as L
import Prelude hiding (foldr, reverse, scanl, scanl1, scanr, scanr1, iterate, repeat, cycle, unzip)
import Test.QuickCheck hiding (NonEmpty)
data NonEmpty a = NonEmpty {
neHead :: a,
neTail :: [a]
} deriving (Eq, Ord, Typeable, Data)
instance Functor NonEmpty where
fmap f (NonEmpty h t) = NonEmpty (f h) (fmap f t)
instance Pointed NonEmpty where
point = return
instance Copointed NonEmpty where
extract = neHead
instance Applicative NonEmpty where
pure = return
(<*>) = ap
instance Monad NonEmpty where
return = flip NonEmpty []
NonEmpty h t >>= f = let NonEmpty a b = f h
k = t >>= toList . f
in NonEmpty a (b ++ k)
instance Comonad NonEmpty where
duplicate x@(NonEmpty _ t) = NonEmpty x (case toNonEmpty t of Nothing -> []
Just u -> toList (duplicate u))
instance Foldable NonEmpty where
foldr f x (NonEmpty h t) = f h (foldr f x t)
foldl f x (NonEmpty h t) = foldl' f x (h:t)
instance Traversable NonEmpty where
traverse f a = NonEmpty <$> head <*> tail <$> traverse f (toList a)
instance (Show a) => Show (NonEmpty a) where
show (NonEmpty h t) = '|' : show (h:t) ++ "|"
instance Semigroup (NonEmpty a) where
NonEmpty a b .++. NonEmpty c d = NonEmpty a (b ++ c:d)
instance Zip NonEmpty where
fzip = list2 zip
instance (Arbitrary a) => Arbitrary (NonEmpty a) where
arbitrary = nonEmpty <$> arbitrary <*> arbitrary
shrink = (unsafeToNonEmpty <$>) . shrink . toList
nonEmpty :: a
-> [a]
-> NonEmpty a
nonEmpty = NonEmpty
(|:) :: a
-> [a]
-> NonEmpty a
(|:) = nonEmpty
toNonEmpty :: [a]
-> Maybe (NonEmpty a)
toNonEmpty [] = Nothing
toNonEmpty (h:t) = Just (NonEmpty h t)
toNonEmpty' :: NonEmpty a
-> [a]
-> NonEmpty a
toNonEmpty' d = fromMaybe d . toNonEmpty
unsafeToNonEmpty :: [a]
-> NonEmpty a
unsafeToNonEmpty = toNonEmpty' (error "unsafeToNonEmpty on empty list")
(.:) :: a
-> NonEmpty a
-> NonEmpty a
a .: NonEmpty h t = NonEmpty a (h:t)
reverse :: NonEmpty a
-> NonEmpty a
reverse = list L.reverse
scanl :: (b -> a -> b)
-> b
-> NonEmpty a
-> NonEmpty b
scanl = (list .) . L.scanl
scanl1 :: (a -> a -> a)
-> NonEmpty a
-> NonEmpty a
scanl1 = list . L.scanl1
scanr :: (a -> b -> b)
-> b
-> NonEmpty a
-> NonEmpty b
scanr = (list .) . L.scanr
scanr1 :: (a -> a -> a)
-> NonEmpty a
-> NonEmpty a
scanr1 = list . L.scanr1
iterate :: (a -> a)
-> a
-> NonEmpty a
iterate = (unsafeToNonEmpty .) . L.iterate
cycle :: (Foldable f) =>
f a
-> NonEmpty a
cycle = list L.cycle
inits :: [a]
-> NonEmpty [a]
inits = unsafeToNonEmpty . L.inits
tails :: [a]
-> NonEmpty [a]
tails = unsafeToNonEmpty . L.tails
sort :: (Ord a) =>
NonEmpty a
-> NonEmpty a
sort = list L.sort
insert :: (Ord a) =>
a
-> NonEmpty a
-> NonEmpty a
insert a = unsafeToNonEmpty . L.insert a . toList
unzip :: NonEmpty (a, b)
-> (NonEmpty a, NonEmpty b)
unzip = (unsafeToNonEmpty *** unsafeToNonEmpty) . L.unzip . toList
list :: Foldable f =>
([a] -> [b])
-> f a
-> NonEmpty b
list = (unsafeToNonEmpty .) . (. toList)
list2 :: Foldable f =>
([a] -> [b] -> [c])
-> f a
-> f b
-> NonEmpty c
list2 f a b = unsafeToNonEmpty (f (toList a) (toList b))