{-# LANGUAGE FlexibleContexts #-}


{-
Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>

All rights reserved.

For license and copyright information, see the file COPYRIGHT

-}

{- |
   Module     : Data.ListLike.Utils
   Copyright  : Copyright (C) 2007 John Goerzen
   License    : BSD3

   Maintainer : David Fox <dsf@seereason.com>, Andreas Abel
   Stability  : stable
   Portability: portable

Utilities for 'Data.ListLike.ListLike' and friends.  More functions
similar to 'Data.List' but not part of the main typeclass.

Written by John Goerzen, jgoerzen\@complete.org
-}

module Data.ListLike.Utils
    (and, or, sum, product, zip, zipWith, unzip, sequence_, toMonadPlus, list,
     intercalate
    ) where
import Prelude hiding (length, head, last, null, tail, map, filter, concat,
                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,
                       maximum, minimum, iterate, span, break, takeWhile,
                       dropWhile, reverse, zip, zipWith, sequence,
                       sequence_, mapM, mapM_, concatMap, and, or, sum,
                       product, repeat, replicate, cycle, take, drop,
                       splitAt, elem, notElem, unzip, lines, words,
                       unlines, unwords, foldMap)
import Control.Monad (MonadPlus(..))
import Data.ListLike.Base
import Data.ListLike.FoldableLL
import Data.Monoid

-- | Returns True if all elements are True
and :: ListLike full Bool => full -> Bool
and :: forall full. ListLike full Bool => full -> Bool
and = (Bool -> Bool) -> full -> Bool
forall full item.
ListLike full item =>
(item -> Bool) -> full -> Bool
all (Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
True)

-- | Returns True if any element is True
or :: ListLike full Bool => full -> Bool
or :: forall full. ListLike full Bool => full -> Bool
or = (Bool -> Bool) -> full -> Bool
forall full item.
ListLike full item =>
(item -> Bool) -> full -> Bool
any (Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
True)

-- | The sum of the list
sum :: (Num a, ListLike full a) => full -> a
sum :: forall a full. (Num a, ListLike full a) => full -> a
sum = Sum a -> a
forall a. Sum a -> a
getSum (Sum a -> a) -> (full -> Sum a) -> full -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Sum a) -> full -> Sum a
forall full item m.
(FoldableLL full item, Monoid m) =>
(item -> m) -> full -> m
foldMap a -> Sum a
forall a. a -> Sum a
Sum

-- | The product of the list
product :: (Num a, ListLike full a) => full -> a
product :: forall a full. (Num a, ListLike full a) => full -> a
product = Product a -> a
forall a. Product a -> a
getProduct (Product a -> a) -> (full -> Product a) -> full -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Product a) -> full -> Product a
forall full item m.
(FoldableLL full item, Monoid m) =>
(item -> m) -> full -> m
foldMap a -> Product a
forall a. a -> Product a
Product

------------------------------ Zipping
-- zip, zipWith  in Base
{- | Converts a list of pairs into two separate lists of elements -}
unzip :: (ListLike full (itema, itemb),
          ListLike ra itema,
          ListLike rb itemb) => full -> (ra, rb)
unzip :: forall full itema itemb ra rb.
(ListLike full (itema, itemb), ListLike ra itema,
 ListLike rb itemb) =>
full -> (ra, rb)
unzip full
inp = ((itema, itemb) -> (ra, rb) -> (ra, rb))
-> (ra, rb) -> full -> (ra, rb)
forall b. ((itema, itemb) -> b -> b) -> b -> full -> b
forall full item b.
FoldableLL full item =>
(item -> b -> b) -> b -> full -> b
foldr (itema, itemb) -> (ra, rb) -> (ra, rb)
(Item ra, Item rb) -> (ra, rb) -> (ra, rb)
forall {a} {b}.
(ListLike a (Item a), ListLike b (Item b)) =>
(Item a, Item b) -> (a, b) -> (a, b)
convert (ra
forall full item. ListLike full item => full
empty, rb
forall full item. ListLike full item => full
empty) full
inp
    where convert :: (Item a, Item b) -> (a, b) -> (a, b)
convert (Item a
a, Item b
b) (a
as, b
bs) = ((Item a -> a -> a
forall full item. ListLike full item => item -> full -> full
cons Item a
a a
as), (Item b -> b -> b
forall full item. ListLike full item => item -> full -> full
cons Item b
b b
bs))

-- | Converts to a MonadPlus instance
toMonadPlus :: (MonadPlus m, ListLike full a) => full -> m (a, full)
toMonadPlus :: forall (m :: * -> *) full a.
(MonadPlus m, ListLike full a) =>
full -> m (a, full)
toMonadPlus = m (a, full)
-> ((a, full) -> m (a, full)) -> Maybe (a, full) -> m (a, full)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m (a, full)
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero (a, full) -> m (a, full)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (a, full) -> m (a, full))
-> (full -> Maybe (a, full)) -> full -> m (a, full)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. full -> Maybe (a, full)
forall full item. ListLike full item => full -> Maybe (item, full)
uncons

-- | List-like destructor (like Data.Maybe.maybe)
list :: ListLike full a => b -> (a -> full -> b) -> full -> b
list :: forall full a b.
ListLike full a =>
b -> (a -> full -> b) -> full -> b
list b
d a -> full -> b
f = b -> ((a, full) -> b) -> Maybe (a, full) -> b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe b
d ((a -> full -> b) -> (a, full) -> b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry a -> full -> b
f) (Maybe (a, full) -> b) -> (full -> Maybe (a, full)) -> full -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. full -> Maybe (a, full)
forall (m :: * -> *) full a.
(MonadPlus m, ListLike full a) =>
full -> m (a, full)
toMonadPlus

-- | 'intercalate' @xs xss@ is equivalent to @('concat' ('intersperse'
-- xs xss))@.  It inserts the list @xs@ in between the lists in @xss@
-- and concatenates the result.
intercalate :: (ListLike a item, ListLike b a)
            => a -> b -> a
intercalate :: forall a item b. (ListLike a item, ListLike b a) => a -> b -> a
intercalate a
x = b -> a
forall full'. ListLike full' a => full' -> a
forall full item full'.
(ListLike full item, ListLike full' full) =>
full' -> full
concat (b -> a) -> (b -> b) -> b -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b -> b
forall full item. ListLike full item => item -> full -> full
intersperse a
x