module Haskell.Data.List.NonEmpty where
open import Haskell.Prim using (Type; List; []; _∘_)
open import Haskell.Prim.Applicative using (Applicative; pure; _<*>_; DefaultApplicative)
open import Haskell.Prim.Functor using (Functor; fmap; _<$_)
open import Haskell.Prim.List using (_++_)
open import Haskell.Prim.Monad using (Monad; _>>=_; DefaultMonad)
open import Haskell.Prim.Monoid using (Semigroup; _<>_)
infixr 5 _:|_ _∷_ _<|_
record NonEmpty (a : Type) : Type where
no-eta-equality
pattern
constructor _:|_
field
head : a
tail : List a
open NonEmpty public
pattern _∷_ x xs = x :| xs
toList : {a : Type} → NonEmpty a → List a
toList xs = head xs List.∷ tail xs
_<|_ : {a : Type} → a → NonEmpty a → NonEmpty a
x <| xs = x ∷ head xs List.∷ tail xs
cons = _<|_
singleton : {a : Type} → a → NonEmpty a
singleton x = x ∷ []
init : {a : Type} → NonEmpty a → List a
init = λ xs → helper (head xs) (tail xs)
module Init where
helper : {a : Type} → a → List a → List a
helper x [] = []
helper x (y List.∷ xs) = x List.∷ helper y xs
last : {a : Type} → NonEmpty a → a
last = λ xs → helper (head xs) (tail xs)
module Last where
helper : {a : Type} → a → List a → a
helper x [] = x
helper _ (y List.∷ xs) = helper y xs
private
bindNonEmpty : ∀ {a b} → NonEmpty a → (a → NonEmpty b) → NonEmpty b
bindNonEmpty xs f = head fx ∷ tail fx ++ fxs
where
fx = f (head xs)
fxs = tail xs >>= (toList ∘ f)
instance
iFunctorNonEmpty : Functor NonEmpty
iFunctorNonEmpty .fmap f xs = f (head xs) ∷ fmap f (tail xs)
iFunctorNonEmpty ._<$_ b xs = b ⦃ head xs ⦄ ∷ (b <$ tail xs)
iDefaultApplicativeNonEmpty : DefaultApplicative NonEmpty
iDefaultApplicativeNonEmpty .DefaultApplicative.pure x = x ∷ []
iDefaultApplicativeNonEmpty .DefaultApplicative._<*>_ fs xs =
bindNonEmpty fs λ f → bindNonEmpty xs λ x → f x ∷ []
iApplicativeNonEmpty : Applicative NonEmpty
iApplicativeNonEmpty = record {DefaultApplicative iDefaultApplicativeNonEmpty}
iDefaultMonadNonEmpty : DefaultMonad NonEmpty
iDefaultMonadNonEmpty .DefaultMonad._>>=_ = bindNonEmpty
iMonadNonEmpty : Monad NonEmpty
iMonadNonEmpty = record {DefaultMonad iDefaultMonadNonEmpty}
iSemigroupNonEmpty : ∀ {a} → Semigroup (NonEmpty a)
iSemigroupNonEmpty ._<>_ (x ∷ xs) ys = x ∷ xs ++ toList ys