{-# LANGUAGE BangPatterns          #-}
{-# LANGUAGE DerivingStrategies    #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE TypeApplications      #-}
{-# LANGUAGE ViewPatterns          #-}

module PlutusTx.Data.List (
    List,
    toBuiltinList,
    fromBuiltinList,
    toSOP,
    fromSOP,
    null,
    append,
    find,
    findIndices,
    filter,
    mapMaybe,
    any,
    all,
    foldMap,
    map,
    length,
    mconcat,
    (<|),
    cons,
    nil,
    singleton,
    uncons,
    and,
    or,
    elem,
    notElem,
    foldr,
    foldl,
    concat,
    concatMap,
    listToMaybe,
    uniqueElement,
    (!!),
    revAppend,
    reverse,
    replicate,
    findIndex,
    unzip,
    zipWith,
    head,
    last,
    tail,
    take,
    drop,
    dropWhile,
    splitAt,
    elemBy,
    nubBy,
    nub,
    partition,
) where

import PlutusTx.Builtins qualified as B
import PlutusTx.Builtins.Internal (BuiltinList)
import PlutusTx.Builtins.Internal qualified as BI
import PlutusTx.IsData.Class (FromData (..), ToData (..), UnsafeFromData (..))
import PlutusTx.Lift (makeLift)
import PlutusTx.Prelude (Bool (..), BuiltinData, Eq (..), Integer, Maybe (..), Monoid (..),
                         Ord (..), Semigroup (..), fmap, not, pure, traceError, ($), (&&), (.),
                         (<$>), (||))
import Prettyprinter (Pretty (..))

import Data.Coerce (coerce)
import Data.Semigroup qualified as Haskell
import PlutusTx.ErrorCodes (indexTooLargeError, lastEmptyListError, negativeIndexError)
import Prelude qualified as Haskell

-- | A list type backed directly by 'Data'. It is meant to be used whenever fast
-- encoding/decoding to/from 'Data' is needed.
newtype List a = List (BuiltinList BuiltinData)
  deriving stock (Int -> List a -> ShowS
[List a] -> ShowS
List a -> String
(Int -> List a -> ShowS)
-> (List a -> String) -> ([List a] -> ShowS) -> Show (List a)
forall a. Int -> List a -> ShowS
forall a. [List a] -> ShowS
forall a. List a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Int -> List a -> ShowS
showsPrec :: Int -> List a -> ShowS
$cshow :: forall a. List a -> String
show :: List a -> String
$cshowList :: forall a. [List a] -> ShowS
showList :: [List a] -> ShowS
Haskell.Show, List a -> List a -> Bool
(List a -> List a -> Bool)
-> (List a -> List a -> Bool) -> Eq (List a)
forall a. List a -> List a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. List a -> List a -> Bool
== :: List a -> List a -> Bool
$c/= :: forall a. List a -> List a -> Bool
/= :: List a -> List a -> Bool
Haskell.Eq)

instance Eq (List a) where
    {-# INLINEABLE (==) #-}
    List BuiltinList BuiltinData
l == :: List a -> List a -> Bool
== List BuiltinList BuiltinData
l' = BuiltinData -> BuiltinData -> Bool
B.equalsData (BuiltinList BuiltinData -> BuiltinData
BI.mkList BuiltinList BuiltinData
l) (BuiltinList BuiltinData -> BuiltinData
BI.mkList BuiltinList BuiltinData
l')

instance ToData (List a) where
    {-# INLINEABLE toBuiltinData #-}
    toBuiltinData :: List a -> BuiltinData
toBuiltinData (List BuiltinList BuiltinData
l) = BuiltinList BuiltinData -> BuiltinData
BI.mkList BuiltinList BuiltinData
l

instance FromData (List a) where
    {-# INLINEABLE fromBuiltinData #-}
    fromBuiltinData :: BuiltinData -> Maybe (List a)
fromBuiltinData = List a -> Maybe (List a)
forall a. a -> Maybe a
Just (List a -> Maybe (List a))
-> (BuiltinData -> List a) -> BuiltinData -> Maybe (List a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinList BuiltinData -> List a
forall a. BuiltinList BuiltinData -> List a
List (BuiltinList BuiltinData -> List a)
-> (BuiltinData -> BuiltinList BuiltinData)
-> BuiltinData
-> List a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinData -> BuiltinList BuiltinData
BI.unsafeDataAsList

instance UnsafeFromData (List a) where
    {-# INLINEABLE unsafeFromBuiltinData #-}
    unsafeFromBuiltinData :: BuiltinData -> List a
unsafeFromBuiltinData = BuiltinList BuiltinData -> List a
forall a. BuiltinList BuiltinData -> List a
List (BuiltinList BuiltinData -> List a)
-> (BuiltinData -> BuiltinList BuiltinData)
-> BuiltinData
-> List a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinData -> BuiltinList BuiltinData
BI.unsafeDataAsList

instance (UnsafeFromData a, Pretty a) => Pretty (List a) where
    {-# INLINEABLE pretty #-}
    pretty :: forall ann. List a -> Doc ann
pretty = [a] -> Doc ann
forall ann. [a] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty ([a] -> Doc ann) -> (List a -> [a]) -> List a -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> [a]
forall a. UnsafeFromData a => List a -> [a]
toSOP

toBuiltinList :: List a -> BuiltinList BuiltinData
toBuiltinList :: forall a. List a -> BuiltinList BuiltinData
toBuiltinList = List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
{-# INLINEABLE toBuiltinList #-}

fromBuiltinList :: BuiltinList BuiltinData -> List a
fromBuiltinList :: forall a. BuiltinList BuiltinData -> List a
fromBuiltinList = BuiltinList BuiltinData -> List a
forall a b. Coercible a b => a -> b
coerce
{-# INLINEABLE fromBuiltinList #-}

null :: List a -> Bool
null :: forall a. List a -> Bool
null = BuiltinList BuiltinData -> Bool
forall a. BuiltinList a -> Bool
B.null (BuiltinList BuiltinData -> Bool)
-> (List a -> BuiltinList BuiltinData) -> List a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @(BuiltinList BuiltinData)
{-# INLINEABLE null #-}

-- | Prepend an element to the list.
infixr 5 <|
(<|) :: (ToData a) => a -> List a -> List a
<| :: forall a. ToData a => a -> List a -> List a
(<|) a
h = BuiltinList BuiltinData -> List a
forall a b. Coercible a b => a -> b
coerce (BuiltinList BuiltinData -> List a)
-> (List a -> BuiltinList BuiltinData) -> List a -> List a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons (a -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData a
h) (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> (List a -> BuiltinList BuiltinData)
-> List a
-> BuiltinList BuiltinData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
{-# INLINEABLE (<|) #-}

-- | Synonym for `<|`.
cons :: (ToData a) => a -> List a -> List a
cons :: forall a. ToData a => a -> List a -> List a
cons = a -> List a -> List a
forall a. ToData a => a -> List a -> List a
(<|)
{-# INLINEABLE cons #-}

-- | Construct an empty list.
nil :: List a
nil :: forall a. List a
nil = BuiltinList BuiltinData -> List a
forall a. BuiltinList BuiltinData -> List a
List BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
{-# INLINEABLE nil #-}

-- | Create a list from a single element.
singleton :: (ToData a) => a -> List a
singleton :: forall a. ToData a => a -> List a
singleton a
a = a -> List a -> List a
forall a. ToData a => a -> List a -> List a
cons a
a List a
forall a. List a
nil
{-# INLINEABLE singleton #-}

append :: List a -> List a -> List a
append :: forall a. List a -> List a -> List a
append (List BuiltinList BuiltinData
l) (List BuiltinList BuiltinData
l') = BuiltinList BuiltinData -> List a
forall a. BuiltinList BuiltinData -> List a
List (BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
l)
  where
    go :: BuiltinList BuiltinData -> BuiltinList BuiltinData
go =
        BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList BuiltinData
l'
            (\BuiltinData
h BuiltinList BuiltinData
t -> BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons BuiltinData
h (BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
t))
{-# INLINEABLE append #-}

instance Semigroup (List a) where
    <> :: List a -> List a -> List a
(<>) = List a -> List a -> List a
forall a. List a -> List a -> List a
append
    {-# INLINEABLE (<>) #-}

instance Monoid (List a) where
    mempty :: List a
mempty = List a
forall a. List a
nil
    {-# INLINEABLE mempty #-}

instance Haskell.Semigroup  (List a) where
    <> :: List a -> List a -> List a
(<>) = List a -> List a -> List a
forall a. List a -> List a -> List a
append
    {-# INLINEABLE (<>) #-}

instance Haskell.Monoid (List a) where
    mempty :: List a
mempty = List a
forall a. List a
nil
    {-# INLINEABLE mempty #-}

-- | Convert a data-backed list to a sums of products list.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
toSOP :: (UnsafeFromData a) => List a -> [a]
toSOP :: forall a. UnsafeFromData a => List a -> [a]
toSOP = BuiltinList BuiltinData -> [a]
go (BuiltinList BuiltinData -> [a])
-> (List a -> BuiltinList BuiltinData) -> List a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> [a]
go = [a]
-> (BuiltinData -> BuiltinList BuiltinData -> [a])
-> BuiltinList BuiltinData
-> [a]
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList' [] (\BuiltinData
h BuiltinList BuiltinData
t -> BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h a -> [a] -> [a]
forall a. a -> [a] -> [a]
: BuiltinList BuiltinData -> [a]
go BuiltinList BuiltinData
t)
{-# INLINEABLE toSOP #-}

-- | Convert a sums of products list to a data-backed list.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to encode to 'BuiltinData'.
fromSOP :: (ToData a) => [a] -> List a
fromSOP :: forall a. ToData a => [a] -> List a
fromSOP = BuiltinList BuiltinData -> List a
forall a b. Coercible a b => a -> b
coerce (BuiltinList BuiltinData -> List a)
-> ([a] -> BuiltinList BuiltinData) -> [a] -> List a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinData -> BuiltinList BuiltinData
BI.unsafeDataAsList (BuiltinData -> BuiltinList BuiltinData)
-> ([a] -> BuiltinData) -> [a] -> BuiltinList BuiltinData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [BuiltinData] -> BuiltinData
B.mkList ([BuiltinData] -> BuiltinData)
-> ([a] -> [BuiltinData]) -> [a] -> BuiltinData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> BuiltinData) -> [a] -> [BuiltinData]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData
{-# INLINEABLE fromSOP #-}

-- | Find the first element that satisfies a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
find :: (UnsafeFromData a) => (a -> Bool) -> List a -> Maybe a
find :: forall a. UnsafeFromData a => (a -> Bool) -> List a -> Maybe a
find a -> Bool
pred' = BuiltinList BuiltinData -> Maybe a
go (BuiltinList BuiltinData -> Maybe a)
-> (List a -> BuiltinList BuiltinData) -> List a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Maybe a
go =
        Maybe a
-> (BuiltinData -> BuiltinList BuiltinData -> Maybe a)
-> BuiltinList BuiltinData
-> Maybe a
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Maybe a
forall a. Maybe a
Nothing
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let h' :: a
h' = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                in
                    if a -> Bool
pred' a
h'
                        then a -> Maybe a
forall a. a -> Maybe a
Just a
h'
                        else BuiltinList BuiltinData -> Maybe a
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE find #-}

-- | Find the indices of all elements that satisfy a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
findIndices :: (UnsafeFromData a) => (a -> Bool) -> List a -> List Integer
findIndices :: forall a. UnsafeFromData a => (a -> Bool) -> List a -> List Integer
findIndices a -> Bool
pred' = Integer -> BuiltinList BuiltinData -> List Integer
go Integer
0 (BuiltinList BuiltinData -> List Integer)
-> (List a -> BuiltinList BuiltinData) -> List a -> List Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: Integer -> BuiltinList BuiltinData -> List Integer
go Integer
i =
        List Integer
-> (BuiltinData -> BuiltinList BuiltinData -> List Integer)
-> BuiltinList BuiltinData
-> List Integer
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            List Integer
forall a. Monoid a => a
mempty
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let h' :: a
h' = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                    indices :: List Integer
indices = Integer -> BuiltinList BuiltinData -> List Integer
go (Integer -> Integer -> Integer
B.addInteger Integer
1 Integer
i) BuiltinList BuiltinData
t
                in
                    if a -> Bool
pred' a
h'
                        then Integer
i Integer -> List Integer -> List Integer
forall a. ToData a => a -> List a -> List a
`cons` List Integer
indices
                        else List Integer
indices
            )
{-# INLINEABLE findIndices #-}

-- | Filter a list using a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
filter :: (UnsafeFromData a, ToData a) => (a -> Bool) -> List a -> List a
filter :: forall a.
(UnsafeFromData a, ToData a) =>
(a -> Bool) -> List a -> List a
filter a -> Bool
pred1 = BuiltinList BuiltinData -> List a
go (BuiltinList BuiltinData -> List a)
-> (List a -> BuiltinList BuiltinData) -> List a -> List a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> List a
go =
        List a
-> (BuiltinData -> BuiltinList BuiltinData -> List a)
-> BuiltinList BuiltinData
-> List a
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            List a
forall a. Monoid a => a
mempty
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let h' :: a
h' = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                in if a -> Bool
pred1 a
h' then a
h' a -> List a -> List a
forall a. ToData a => a -> List a -> List a
`cons` BuiltinList BuiltinData -> List a
go BuiltinList BuiltinData
t else BuiltinList BuiltinData -> List a
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE filter #-}

-- | Map a function over a list and discard the results that are 'Nothing'.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData', or if the result of applying
-- 'f' is expensive to encode to 'BuiltinData'.
mapMaybe :: (UnsafeFromData a, ToData b) => (a -> Maybe b) -> List a -> List b
mapMaybe :: forall a b.
(UnsafeFromData a, ToData b) =>
(a -> Maybe b) -> List a -> List b
mapMaybe a -> Maybe b
f = BuiltinList BuiltinData -> List b
go (BuiltinList BuiltinData -> List b)
-> (List a -> BuiltinList BuiltinData) -> List a -> List b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> List b
go =
        List b
-> (BuiltinData -> BuiltinList BuiltinData -> List b)
-> BuiltinList BuiltinData
-> List b
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            List b
forall a. Monoid a => a
mempty
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                case a -> Maybe b
f (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) of
                    Just b
b  -> b
b b -> List b -> List b
forall a. ToData a => a -> List a -> List a
`cons` BuiltinList BuiltinData -> List b
go BuiltinList BuiltinData
t
                    Maybe b
Nothing -> BuiltinList BuiltinData -> List b
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE mapMaybe #-}

-- | Check if any element in the list satisfies a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
any :: (UnsafeFromData a) => (a -> Bool) -> List a -> Bool
any :: forall a. UnsafeFromData a => (a -> Bool) -> List a -> Bool
any a -> Bool
pred1 = BuiltinList BuiltinData -> Bool
go (BuiltinList BuiltinData -> Bool)
-> (List a -> BuiltinList BuiltinData) -> List a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Bool
go =
        Bool
-> (BuiltinData -> BuiltinList BuiltinData -> Bool)
-> BuiltinList BuiltinData
-> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Bool
False
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                a -> Bool
pred1 (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) Bool -> Bool -> Bool
|| BuiltinList BuiltinData -> Bool
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE any #-}

-- | Check if all elements in the list satisfy a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
all :: (UnsafeFromData a) => (a -> Bool) -> List a -> Bool
all :: forall a. UnsafeFromData a => (a -> Bool) -> List a -> Bool
all a -> Bool
pred1 = BuiltinList BuiltinData -> Bool
go (BuiltinList BuiltinData -> Bool)
-> (List a -> BuiltinList BuiltinData) -> List a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Bool
go =
        Bool
-> (BuiltinData -> BuiltinList BuiltinData -> Bool)
-> BuiltinList BuiltinData
-> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Bool
True
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                a -> Bool
pred1 (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) Bool -> Bool -> Bool
&& BuiltinList BuiltinData -> Bool
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE all #-}

-- | Fold a list using a monoid.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
foldMap :: (UnsafeFromData a, Monoid m) => (a -> m) -> List a -> m
foldMap :: forall a m. (UnsafeFromData a, Monoid m) => (a -> m) -> List a -> m
foldMap a -> m
f = BuiltinList BuiltinData -> m
go (BuiltinList BuiltinData -> m)
-> (List a -> BuiltinList BuiltinData) -> List a -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> m
go =
        m
-> (BuiltinData -> BuiltinList BuiltinData -> m)
-> BuiltinList BuiltinData
-> m
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            m
forall a. Monoid a => a
mempty
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let h' :: a
h' = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                in a -> m
f a
h' m -> m -> m
forall a. Semigroup a => a -> a -> a
<> BuiltinList BuiltinData -> m
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE foldMap #-}

-- | Map a function over a list.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData', or if the result of applying
-- 'f' is expensive to encode to 'BuiltinData'.
map :: (UnsafeFromData a, ToData b) => (a -> b) -> List a -> List b
map :: forall a b.
(UnsafeFromData a, ToData b) =>
(a -> b) -> List a -> List b
map a -> b
f = (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a -> List b
forall a b. Coercible a b => a -> b
coerce BuiltinList BuiltinData -> BuiltinList BuiltinData
go
  where
    go :: BuiltinList BuiltinData -> BuiltinList BuiltinData
go =
        BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons
                    (b -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData (b -> BuiltinData) -> b -> BuiltinData
forall a b. (a -> b) -> a -> b
$ a -> b
f (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
$ BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h)
                    (BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
t)
            )
{-# INLINEABLE map #-}

-- | Get the length of a list.
length :: List a -> Integer
length :: forall a. List a -> Integer
length (List BuiltinList BuiltinData
l) = BuiltinList BuiltinData -> Integer
forall {a}. BuiltinList a -> Integer
go BuiltinList BuiltinData
l
  where
    go :: BuiltinList a -> Integer
go = Integer
-> (a -> BuiltinList a -> Integer) -> BuiltinList a -> Integer
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
BI.caseList' Integer
0 (\a
_ -> Integer -> Integer -> Integer
B.addInteger Integer
1 (Integer -> Integer)
-> (BuiltinList a -> Integer) -> BuiltinList a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinList a -> Integer
go)
{-# INLINEABLE length #-}

-- | Concatenate a list of monoids.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
mconcat :: (Monoid a, UnsafeFromData a) => List a -> a
mconcat :: forall a. (Monoid a, UnsafeFromData a) => List a -> a
mconcat = BuiltinList BuiltinData -> a
go (BuiltinList BuiltinData -> a)
-> (List a -> BuiltinList BuiltinData) -> List a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> a
go =
        a
-> (BuiltinData -> BuiltinList BuiltinData -> a)
-> BuiltinList BuiltinData
-> a
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            a
forall a. Monoid a => a
mempty
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h a -> a -> a
forall a. Semigroup a => a -> a -> a
<> BuiltinList BuiltinData -> a
go BuiltinList BuiltinData
t
            )
{-# INLINABLE mconcat #-}

-- | Get the first element of a list and the rest of the list.
uncons :: (UnsafeFromData a) => List a -> Maybe (a, List a)
uncons :: forall a. UnsafeFromData a => List a -> Maybe (a, List a)
uncons (List BuiltinList BuiltinData
l) = do
    (BuiltinData
h, BuiltinList BuiltinData
t) <- BuiltinList BuiltinData
-> Maybe (BuiltinData, BuiltinList BuiltinData)
forall a. BuiltinList a -> Maybe (a, BuiltinList a)
B.uncons BuiltinList BuiltinData
l
    (a, List a) -> Maybe (a, List a)
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h, BuiltinList BuiltinData -> List a
forall a. BuiltinList BuiltinData -> List a
List BuiltinList BuiltinData
t)
{-# INLINEABLE uncons #-}

-- | Check if all elements in the list are 'True'.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
and :: List Bool -> Bool
and :: List Bool -> Bool
and = BuiltinList BuiltinData -> Bool
go (BuiltinList BuiltinData -> Bool)
-> (List Bool -> BuiltinList BuiltinData) -> List Bool -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List Bool -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Bool
go =
        Bool
-> (BuiltinData -> BuiltinList BuiltinData -> Bool)
-> BuiltinList BuiltinData
-> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Bool
True
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                BuiltinData -> Bool
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h Bool -> Bool -> Bool
&& BuiltinList BuiltinData -> Bool
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE and #-}

-- | Check if any element in the list is 'True'.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
or :: List Bool -> Bool
or :: List Bool -> Bool
or = BuiltinList BuiltinData -> Bool
go (BuiltinList BuiltinData -> Bool)
-> (List Bool -> BuiltinList BuiltinData) -> List Bool -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List Bool -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Bool
go =
        Bool
-> (BuiltinData -> BuiltinList BuiltinData -> Bool)
-> BuiltinList BuiltinData
-> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Bool
False
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                BuiltinData -> Bool
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h Bool -> Bool -> Bool
|| BuiltinList BuiltinData -> Bool
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE or #-}

-- | Check if an element is in the list.
-- Note: this function can leverage the better performance of equality checks
-- for 'BuiltinData'.
elem :: (ToData a) => a -> List a -> Bool
elem :: forall a. ToData a => a -> List a -> Bool
elem a
x = BuiltinList BuiltinData -> Bool
go (BuiltinList BuiltinData -> Bool)
-> (List a -> BuiltinList BuiltinData) -> List a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Bool
go =
        let x' :: BuiltinData
x' = a -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData a
x
        in Bool
-> (BuiltinData -> BuiltinList BuiltinData -> Bool)
-> BuiltinList BuiltinData
-> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Bool
False
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                BuiltinData
x' BuiltinData -> BuiltinData -> Bool
forall a. Eq a => a -> a -> Bool
== BuiltinData
h Bool -> Bool -> Bool
|| BuiltinList BuiltinData -> Bool
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE elem #-}

-- | Check if an element is not in the list.
notElem :: (ToData a) => a -> List a -> Bool
notElem :: forall a. ToData a => a -> List a -> Bool
notElem a
x = Bool -> Bool
not (Bool -> Bool) -> (List a -> Bool) -> List a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> List a -> Bool
forall a. ToData a => a -> List a -> Bool
elem a
x
{-# INLINEABLE notElem #-}

-- | Fold a list from the right.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
foldr :: (UnsafeFromData a) => (a -> b -> b) -> b -> List a -> b
foldr :: forall a b. UnsafeFromData a => (a -> b -> b) -> b -> List a -> b
foldr a -> b -> b
f b
z = b -> BuiltinList BuiltinData -> b
go b
z (BuiltinList BuiltinData -> b)
-> (List a -> BuiltinList BuiltinData) -> List a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: b -> BuiltinList BuiltinData -> b
go b
u =
        b
-> (BuiltinData -> BuiltinList BuiltinData -> b)
-> BuiltinList BuiltinData
-> b
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            b
u
            (\BuiltinData
h ->
                a -> b -> b
f (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) (b -> b)
-> (BuiltinList BuiltinData -> b) -> BuiltinList BuiltinData -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> BuiltinList BuiltinData -> b
go b
u
            )
{-# INLINEABLE foldr #-}

-- | Fold a list from the left.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
foldl :: (UnsafeFromData a) => (b -> a -> b) -> b -> List a -> b
foldl :: forall a b. UnsafeFromData a => (b -> a -> b) -> b -> List a -> b
foldl b -> a -> b
f b
z = b -> BuiltinList BuiltinData -> b
go b
z (BuiltinList BuiltinData -> b)
-> (List a -> BuiltinList BuiltinData) -> List a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: b -> BuiltinList BuiltinData -> b
go b
acc =
        b
-> (BuiltinData -> BuiltinList BuiltinData -> b)
-> BuiltinList BuiltinData
-> b
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            b
acc
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let h' :: a
h' = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                in b -> BuiltinList BuiltinData -> b
go (b -> a -> b
f b
acc a
h') BuiltinList BuiltinData
t
            )
{-# INLINEABLE foldl #-}

-- | Flatten a list of lists into a single list.
concat :: List (List a) -> List a
concat :: forall a. List (List a) -> List a
concat = (List a -> List a -> List a) -> List a -> List (List a) -> List a
forall a b. UnsafeFromData a => (a -> b -> b) -> b -> List a -> b
foldr List a -> List a -> List a
forall a. List a -> List a -> List a
append List a
forall a. Monoid a => a
mempty
{-# INLINEABLE concat #-}

-- | Map a function over a list and concatenate the results.
concatMap :: (UnsafeFromData a) => (a -> List b) -> List a -> List b
concatMap :: forall a b. UnsafeFromData a => (a -> List b) -> List a -> List b
concatMap = (a -> List b) -> List a -> List b
forall a m. (UnsafeFromData a, Monoid m) => (a -> m) -> List a -> m
foldMap
{-# INLINEABLE concatMap #-}

-- | Get the first element of a list if it is not empty.
listToMaybe :: (UnsafeFromData a) => List a -> Maybe a
listToMaybe :: forall a. UnsafeFromData a => List a -> Maybe a
listToMaybe (List BuiltinList BuiltinData
l) = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData (BuiltinData -> a) -> Maybe BuiltinData -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BuiltinList BuiltinData -> Maybe BuiltinData
forall a. BuiltinList a -> Maybe a
B.headMaybe BuiltinList BuiltinData
l
{-# INLINEABLE listToMaybe #-}

-- | Get the element of a list if it has exactly one element.
uniqueElement :: (UnsafeFromData a) => List a -> Maybe a
uniqueElement :: forall a. UnsafeFromData a => List a -> Maybe a
uniqueElement (List BuiltinList BuiltinData
l) = do
    (BuiltinData
h, BuiltinList BuiltinData
t) <- BuiltinList BuiltinData
-> Maybe (BuiltinData, BuiltinList BuiltinData)
forall a. BuiltinList a -> Maybe (a, BuiltinList a)
B.uncons BuiltinList BuiltinData
l
    if BuiltinList BuiltinData -> Bool
forall a. BuiltinList a -> Bool
B.null BuiltinList BuiltinData
t
        then a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
        else Maybe a
forall a. Maybe a
Nothing
{-# INLINEABLE uniqueElement #-}

-- | Get the element at a given index.
-- Warning: this is a partial function and will fail if the index is negative or
-- greater than the length of the list.
-- Note: this function has the same precedence as (!!) from 'PlutusTx.List'.
infixl 9 !!
(!!) :: (UnsafeFromData a) => List a -> Integer -> a
(List BuiltinList BuiltinData
l) !! :: forall a. UnsafeFromData a => List a -> Integer -> a
!! Integer
n =
    if Integer -> Integer -> Bool
B.lessThanInteger Integer
n Integer
0
        then BuiltinString -> a
forall a. BuiltinString -> a
traceError BuiltinString
negativeIndexError
        else Integer -> BuiltinList BuiltinData -> a
forall {r}.
UnsafeFromData r =>
Integer -> BuiltinList BuiltinData -> r
go Integer
n BuiltinList BuiltinData
l
  where
    go :: Integer -> BuiltinList BuiltinData -> r
go Integer
n' =
        (() -> r)
-> (BuiltinData -> BuiltinList BuiltinData -> r)
-> BuiltinList BuiltinData
-> r
forall a r.
(() -> r) -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList
            (\() -> BuiltinString -> r
forall a. BuiltinString -> a
traceError BuiltinString
indexTooLargeError)
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                if Integer -> Integer -> Bool
B.equalsInteger Integer
n' Integer
0
                    then BuiltinData -> r
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                    else Integer -> BuiltinList BuiltinData -> r
go (Integer -> Integer -> Integer
B.subtractInteger Integer
n' Integer
1) BuiltinList BuiltinData
t
            )
{-# INLINABLE (!!) #-}

-- | Append two lists in reverse order.
revAppend :: List a -> List a -> List a
revAppend :: forall a. List a -> List a -> List a
revAppend (List BuiltinList BuiltinData
l) (List BuiltinList BuiltinData
l') = BuiltinList BuiltinData -> List a
forall a. BuiltinList BuiltinData -> List a
List (BuiltinList BuiltinData -> List a)
-> BuiltinList BuiltinData -> List a
forall a b. (a -> b) -> a -> b
$ BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall {a}. BuiltinList a -> BuiltinList a -> BuiltinList a
rev BuiltinList BuiltinData
l BuiltinList BuiltinData
l'
  where
    rev :: BuiltinList a -> BuiltinList a -> BuiltinList a
rev BuiltinList a
l1 BuiltinList a
l2 =
        BuiltinList a
-> (a -> BuiltinList a -> BuiltinList a)
-> BuiltinList a
-> BuiltinList a
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList a
l2
            (\a
h BuiltinList a
t -> BuiltinList a -> BuiltinList a -> BuiltinList a
rev BuiltinList a
t (a -> BuiltinList a -> BuiltinList a
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons a
h BuiltinList a
l2))
            BuiltinList a
l1
{-# INLINEABLE revAppend #-}

-- | Reverse a list.
reverse :: List a -> List a
reverse :: forall a. List a -> List a
reverse List a
l = List a -> List a -> List a
forall a. List a -> List a -> List a
revAppend List a
l List a
forall a. Monoid a => a
mempty
{-# INLINEABLE reverse #-}

-- | Replicate a value n times.
replicate :: (ToData a) =>  Integer -> a -> List a
replicate :: forall a. ToData a => Integer -> a -> List a
replicate Integer
n (a -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData -> BuiltinData
x) = BuiltinList BuiltinData -> List a
forall a b. Coercible a b => a -> b
coerce (BuiltinList BuiltinData -> List a)
-> BuiltinList BuiltinData -> List a
forall a b. (a -> b) -> a -> b
$ Integer -> BuiltinList BuiltinData
go Integer
n
  where
    go :: Integer -> BuiltinList BuiltinData
go Integer
n' =
        if Integer -> Integer -> Bool
B.equalsInteger Integer
n' Integer
0
            then BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
            else BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons BuiltinData
x (Integer -> BuiltinList BuiltinData
go (Integer -> Integer -> Integer
B.subtractInteger Integer
n' Integer
1))
{-# INLINEABLE replicate #-}

-- | Find the index of the first element that satisfies a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
findIndex :: (UnsafeFromData a) => (a -> Bool) -> List a -> Maybe Integer
findIndex :: forall a.
UnsafeFromData a =>
(a -> Bool) -> List a -> Maybe Integer
findIndex a -> Bool
pred' = Integer -> BuiltinList BuiltinData -> Maybe Integer
go Integer
0 (BuiltinList BuiltinData -> Maybe Integer)
-> (List a -> BuiltinList BuiltinData) -> List a -> Maybe Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: Integer -> BuiltinList BuiltinData -> Maybe Integer
go Integer
i =
        Maybe Integer
-> (BuiltinData -> BuiltinList BuiltinData -> Maybe Integer)
-> BuiltinList BuiltinData
-> Maybe Integer
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Maybe Integer
forall a. Maybe a
Nothing
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                if a -> Bool
pred' (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) then Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
i else Integer -> BuiltinList BuiltinData -> Maybe Integer
go (Integer -> Integer -> Integer
B.addInteger Integer
1 Integer
i) BuiltinList BuiltinData
t
            )
{-# INLINEABLE findIndex #-}

-- | Split a list of pairs into a pair of lists.
unzip :: forall a b . List (a, b) -> (List a, List b)
unzip :: forall a b. List (a, b) -> (List a, List b)
unzip =
    (BuiltinList BuiltinData
 -> (BuiltinList BuiltinData, BuiltinList BuiltinData))
-> List (a, b) -> (List a, List b)
forall a b. Coercible a b => a -> b
coerce BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go
  where
    go :: BuiltinList BuiltinData -> (BuiltinList BuiltinData, BuiltinList BuiltinData)
    go :: BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go =
        (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (BuiltinData
    -> BuiltinList BuiltinData
    -> (BuiltinList BuiltinData, BuiltinList BuiltinData))
-> BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            (BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil, BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil)
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let (BuiltinData
a, BuiltinData
b) = BuiltinData -> (BuiltinData, BuiltinData)
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                    (BuiltinList BuiltinData
as, BuiltinList BuiltinData
bs) = BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go BuiltinList BuiltinData
t
                in (BuiltinData
a BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
`BI.mkCons` BuiltinList BuiltinData
as, BuiltinData
b BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
`BI.mkCons` BuiltinList BuiltinData
bs)
            )
{-# INLINEABLE unzip #-}

-- | Zip two lists together using a function.
-- Warning: this function can be very inefficient if the lists contain elements
-- that are expensive to decode from 'BuiltinData', or if the result of applying
-- 'f' is expensive to encode to 'BuiltinData'.
zipWith
    :: (UnsafeFromData a, UnsafeFromData b, ToData c)
    => (a -> b -> c) -> List a -> List b -> List c
zipWith :: forall a b c.
(UnsafeFromData a, UnsafeFromData b, ToData c) =>
(a -> b -> c) -> List a -> List b -> List c
zipWith a -> b -> c
f = (BuiltinList BuiltinData
 -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a -> List b -> List c
forall a b. Coercible a b => a -> b
coerce BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go
  where
    go :: BuiltinList BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
    go :: BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
l1' BuiltinList BuiltinData
l2' =
        BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
            (\BuiltinData
h1 BuiltinList BuiltinData
t1 ->
                BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
                    BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
                    (\BuiltinData
h2 BuiltinList BuiltinData
t2 ->
                        BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons
                            (c -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData
                            (c -> BuiltinData) -> c -> BuiltinData
forall a b. (a -> b) -> a -> b
$ a -> b -> c
f
                                (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h1)
                                (BuiltinData -> b
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h2)
                            )
                            (BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
t1 BuiltinList BuiltinData
t2)
                    )
                    BuiltinList BuiltinData
l2'
            )
            BuiltinList BuiltinData
l1'
{-# INLINEABLE zipWith #-}

-- | Return the head of a list.
-- Warning: this is a partial function and will fail if the list is empty.
head :: forall a . (UnsafeFromData a) => List a -> a
head :: forall a. UnsafeFromData a => List a -> a
head =
    forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce
        @(BuiltinList BuiltinData -> a)
        @(List a -> a)
        (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData (BuiltinData -> a)
-> (BuiltinList BuiltinData -> BuiltinData)
-> BuiltinList BuiltinData
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinList BuiltinData -> BuiltinData
forall a. BuiltinList a -> a
B.head)
{-# INLINEABLE head #-}

-- | Return the last element of a list.
-- Warning: this is a partial function and will fail if the list is empty.
last :: forall a . (UnsafeFromData a) => List a -> a
last :: forall a. UnsafeFromData a => List a -> a
last =
    forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce
        @(BuiltinList BuiltinData -> a)
        @(List a -> a)
        (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData (BuiltinData -> a)
-> (BuiltinList BuiltinData -> BuiltinData)
-> BuiltinList BuiltinData
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinList BuiltinData -> BuiltinData
go)
  where
    go :: BuiltinList BuiltinData -> BuiltinData
    go :: BuiltinList BuiltinData -> BuiltinData
go =
        (() -> BuiltinData)
-> (BuiltinData -> BuiltinList BuiltinData -> BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinData
forall a r.
(() -> r) -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList
            (\() -> BuiltinString -> BuiltinData
forall a. BuiltinString -> a
traceError BuiltinString
lastEmptyListError)
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                if BuiltinList BuiltinData -> Bool
forall a. BuiltinList a -> Bool
B.null BuiltinList BuiltinData
t
                    then BuiltinData
h
                    else BuiltinList BuiltinData -> BuiltinData
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE last #-}

-- | Return the tail of a list.
-- Warning: this is a partial function and will fail if the list is empty.
tail :: forall a . List a -> List a
tail :: forall a. List a -> List a
tail = forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @(BuiltinList BuiltinData) @(List a) (BuiltinList BuiltinData -> List a)
-> (List a -> BuiltinList BuiltinData) -> List a -> List a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. BuiltinList a -> BuiltinList a
B.tail (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> (List a -> BuiltinList BuiltinData)
-> List a
-> BuiltinList BuiltinData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
{-# INLINEABLE tail #-}

-- | Take the first n elements from the list.
take :: forall a . Integer -> List a -> List a
take :: forall a. Integer -> List a -> List a
take Integer
n = (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a -> List a
forall a b. Coercible a b => a -> b
coerce ((BuiltinList BuiltinData -> BuiltinList BuiltinData)
 -> List a -> List a)
-> (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a
-> List a
forall a b. (a -> b) -> a -> b
$ Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
go Integer
n
  where
    go :: Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
    go :: Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
go Integer
n' =
        BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                if Integer -> Integer -> Bool
B.equalsInteger Integer
n' Integer
0
                    then BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
                    else BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons BuiltinData
h (Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
go (Integer -> Integer -> Integer
B.subtractInteger Integer
n' Integer
1) BuiltinList BuiltinData
t)
            )
{-# INLINEABLE take #-}

-- | Drop the first n elements from the list.
drop :: forall a . Integer -> List a -> List a
drop :: forall a. Integer -> List a -> List a
drop Integer
n = (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a -> List a
forall a b. Coercible a b => a -> b
coerce ((BuiltinList BuiltinData -> BuiltinList BuiltinData)
 -> List a -> List a)
-> (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a
-> List a
forall a b. (a -> b) -> a -> b
$ Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
go Integer
n
  where
    go :: Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
    go :: Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
go Integer
n' BuiltinList BuiltinData
xs =
        if Integer
n' Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0
            then BuiltinList BuiltinData
xs
            else
                BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
                    BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
                    (\BuiltinData
_ ->
                        Integer -> BuiltinList BuiltinData -> BuiltinList BuiltinData
go (Integer -> Integer -> Integer
B.subtractInteger Integer
n' Integer
1)
                    )
                    BuiltinList BuiltinData
xs
{-# INLINEABLE drop #-}

-- | Drop elements from the list while the predicate holds.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
dropWhile :: forall a . (UnsafeFromData a) => (a -> Bool) -> List a -> List a
dropWhile :: forall a. UnsafeFromData a => (a -> Bool) -> List a -> List a
dropWhile a -> Bool
pred1 =
    forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @(List a -> List a) ((BuiltinList BuiltinData -> BuiltinList BuiltinData)
 -> List a -> List a)
-> (BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> List a
-> List a
forall a b. (a -> b) -> a -> b
$ BuiltinList BuiltinData -> BuiltinList BuiltinData
go
  where
    go :: BuiltinList BuiltinData -> BuiltinList BuiltinData
    go :: BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
xs =
        BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                if a -> Bool
pred1 (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) then BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
t else BuiltinList BuiltinData
xs
            )
            BuiltinList BuiltinData
xs
{-# INLINEABLE dropWhile #-}

-- | Split a list at a given index.
splitAt :: forall a . Integer -> List a -> (List a, List a)
splitAt :: forall a. Integer -> List a -> (List a, List a)
splitAt Integer
n List a
l =
    (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (List a, List a)
forall a b. Coercible a b => a -> b
coerce ((BuiltinList BuiltinData, BuiltinList BuiltinData)
 -> (List a, List a))
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (List a, List a)
forall a b. (a -> b) -> a -> b
$ Integer
-> BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go Integer
n (forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @(BuiltinList BuiltinData) List a
l)
  where
    go :: Integer
-> BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go Integer
n' BuiltinList BuiltinData
xs =
        if Integer
n' Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0
            then (BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil, BuiltinList BuiltinData
xs)
            else
                (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (BuiltinData
    -> BuiltinList BuiltinData
    -> (BuiltinList BuiltinData, BuiltinList BuiltinData))
-> BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
                    (BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil, BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil)
                    (\BuiltinData
h BuiltinList BuiltinData
t ->
                        if Integer -> Integer -> Bool
B.equalsInteger Integer
n' Integer
0
                            then (BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil, forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @(BuiltinList BuiltinData) List a
l)
                            else
                                let (BuiltinList BuiltinData
l1, BuiltinList BuiltinData
l2) = Integer
-> BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go (Integer -> Integer -> Integer
B.subtractInteger Integer
n' Integer
1) BuiltinList BuiltinData
t
                                in (BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons BuiltinData
h BuiltinList BuiltinData
l1, BuiltinList BuiltinData
l2)
                    )
                    BuiltinList BuiltinData
xs
{-# INLINEABLE splitAt #-}

-- | Check if an element satisfying a binary predicate is in the list.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
elemBy :: (UnsafeFromData a) => (a -> a -> Bool) -> a -> List a -> Bool
elemBy :: forall a.
UnsafeFromData a =>
(a -> a -> Bool) -> a -> List a -> Bool
elemBy a -> a -> Bool
pred2 a
x = BuiltinList BuiltinData -> Bool
go (BuiltinList BuiltinData -> Bool)
-> (List a -> BuiltinList BuiltinData) -> List a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce
  where
    go :: BuiltinList BuiltinData -> Bool
go =
        Bool
-> (BuiltinData -> BuiltinList BuiltinData -> Bool)
-> BuiltinList BuiltinData
-> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            Bool
False
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                a -> a -> Bool
pred2 (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) a
x Bool -> Bool -> Bool
|| BuiltinList BuiltinData -> Bool
go BuiltinList BuiltinData
t
            )
{-# INLINEABLE elemBy #-}

-- | Removes elements from the list that satisfy a binary predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
nubBy :: forall a . (UnsafeFromData a) => (a -> a -> Bool) -> List a -> List a
nubBy :: forall a. UnsafeFromData a => (a -> a -> Bool) -> List a -> List a
nubBy a -> a -> Bool
pred2 List a
l =
    forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @(List a) (BuiltinList BuiltinData -> List a)
-> BuiltinList BuiltinData -> List a
forall a b. (a -> b) -> a -> b
$ BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go (forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @(BuiltinList BuiltinData) List a
l) BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
  where
    go :: BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
ys BuiltinList BuiltinData
xs =
        BuiltinList BuiltinData
-> (BuiltinData
    -> BuiltinList BuiltinData -> BuiltinList BuiltinData)
-> BuiltinList BuiltinData
-> BuiltinList BuiltinData
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                if (a -> a -> Bool) -> a -> List a -> Bool
forall a.
UnsafeFromData a =>
(a -> a -> Bool) -> a -> List a -> Bool
elemBy a -> a -> Bool
pred2 (BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h) (BuiltinList BuiltinData -> List a
forall a b. Coercible a b => a -> b
coerce BuiltinList BuiltinData
xs)
                    then BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
t BuiltinList BuiltinData
xs
                    else BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons BuiltinData
h (BuiltinList BuiltinData
-> BuiltinList BuiltinData -> BuiltinList BuiltinData
go BuiltinList BuiltinData
t (BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons BuiltinData
h BuiltinList BuiltinData
xs))
            )
            BuiltinList BuiltinData
ys
{-# INLINEABLE nubBy #-}

-- | Removes duplicate elements from the list.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
nub :: (Eq a, UnsafeFromData a) => List a -> List a
nub :: forall a. (Eq a, UnsafeFromData a) => List a -> List a
nub = (a -> a -> Bool) -> List a -> List a
forall a. UnsafeFromData a => (a -> a -> Bool) -> List a -> List a
nubBy a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
{-# INLINEABLE nub #-}

-- | Partition a list into two lists based on a predicate.
-- Warning: this function can be very inefficient if the list contains elements
-- that are expensive to decode from 'BuiltinData'.
partition :: (UnsafeFromData a) => (a -> Bool) -> List a -> (List a, List a)
partition :: forall a.
UnsafeFromData a =>
(a -> Bool) -> List a -> (List a, List a)
partition a -> Bool
pred1 List a
l =
    (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (List a, List a)
forall a b. Coercible a b => a -> b
coerce ((BuiltinList BuiltinData, BuiltinList BuiltinData)
 -> (List a, List a))
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (List a, List a)
forall a b. (a -> b) -> a -> b
$ BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go (List a -> BuiltinList BuiltinData
forall a b. Coercible a b => a -> b
coerce List a
l)
  where
    go :: BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go =
        (BuiltinList BuiltinData, BuiltinList BuiltinData)
-> (BuiltinData
    -> BuiltinList BuiltinData
    -> (BuiltinList BuiltinData, BuiltinList BuiltinData))
-> BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
            (BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil, BuiltinList BuiltinData
forall arep. MkNil arep => BuiltinList arep
B.mkNil)
            (\BuiltinData
h BuiltinList BuiltinData
t ->
                let h' :: a
h' = BuiltinData -> a
forall a. UnsafeFromData a => BuiltinData -> a
unsafeFromBuiltinData BuiltinData
h
                    (BuiltinList BuiltinData
l1, BuiltinList BuiltinData
l2) = BuiltinList BuiltinData
-> (BuiltinList BuiltinData, BuiltinList BuiltinData)
go BuiltinList BuiltinData
t
                in if a -> Bool
pred1 a
h'
                    then (BuiltinData
h BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
`BI.mkCons` BuiltinList BuiltinData
l1, BuiltinList BuiltinData
l2)
                    else (BuiltinList BuiltinData
l1, BuiltinData
h BuiltinData -> BuiltinList BuiltinData -> BuiltinList BuiltinData
forall a. a -> BuiltinList a -> BuiltinList a
`BI.mkCons` BuiltinList BuiltinData
l2)
            )
{-# INLINEABLE partition #-}

makeLift ''List