{-# LANGUAGE LambdaCase #-}
module PlutusTx.BuiltinList (
BuiltinList,
B.caseList,
B.caseList',
map,
elem,
find,
any,
all,
(!!),
)
where
import Prelude (Bool (..), Integer, Maybe (..), otherwise, (.))
import PlutusTx.Builtins qualified as B
import PlutusTx.Builtins.HasOpaque
import PlutusTx.Builtins.Internal (BuiltinList)
import PlutusTx.Builtins.Internal qualified as BI
import PlutusTx.Eq
import PlutusTx.ErrorCodes
import PlutusTx.Trace (traceError)
infixl 9 !!
map :: forall a b. (MkNil b) => (a -> b) -> BuiltinList a -> BuiltinList b
map :: forall a b. MkNil b => (a -> b) -> BuiltinList a -> BuiltinList b
map a -> b
f = BuiltinList a -> BuiltinList b
go
where
go :: BuiltinList a -> BuiltinList b
go :: BuiltinList a -> BuiltinList b
go =
BuiltinList b
-> (a -> BuiltinList a -> BuiltinList b)
-> BuiltinList a
-> BuiltinList b
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
BuiltinList b
forall arep. MkNil arep => BuiltinList arep
B.mkNil
(\a
x -> b -> BuiltinList b -> BuiltinList b
forall a. a -> BuiltinList a -> BuiltinList a
BI.mkCons (a -> b
f a
x) (BuiltinList b -> BuiltinList b)
-> (BuiltinList a -> BuiltinList b)
-> BuiltinList a
-> BuiltinList b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinList a -> BuiltinList b
go)
{-# INLINEABLE map #-}
elem :: forall a. (Eq a) => a -> BuiltinList a -> Bool
elem :: forall a. Eq a => a -> BuiltinList a -> Bool
elem a
a = BuiltinList a -> Bool
go
where
go :: BuiltinList a -> Bool
go :: BuiltinList a -> Bool
go = Bool -> (a -> BuiltinList a -> Bool) -> BuiltinList a -> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList' Bool
False (\a
x BuiltinList a
xs -> if a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x then Bool
True else BuiltinList a -> Bool
go BuiltinList a
xs)
{-# INLINEABLE elem #-}
find :: forall a. (a -> Bool) -> BuiltinList a -> Maybe a
find :: forall a. (a -> Bool) -> BuiltinList a -> Maybe a
find a -> Bool
p = BuiltinList a -> Maybe a
go
where
go :: BuiltinList a -> Maybe a
go :: BuiltinList a -> Maybe a
go =
Maybe a
-> (a -> BuiltinList a -> Maybe a) -> BuiltinList a -> Maybe a
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList'
Maybe a
forall a. Maybe a
Nothing
(\a
x BuiltinList a
xs -> if a -> Bool
p a
x then a -> Maybe a
forall a. a -> Maybe a
Just a
x else BuiltinList a -> Maybe a
go BuiltinList a
xs)
{-# INLINEABLE find #-}
any :: forall a. (a -> Bool) -> BuiltinList a -> Bool
any :: forall a. (a -> Bool) -> BuiltinList a -> Bool
any a -> Bool
p = BuiltinList a -> Bool
go
where
go :: BuiltinList a -> Bool
go :: BuiltinList a -> Bool
go = Bool -> (a -> BuiltinList a -> Bool) -> BuiltinList a -> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList' Bool
False (\a
x BuiltinList a
xs -> if a -> Bool
p a
x then Bool
True else BuiltinList a -> Bool
go BuiltinList a
xs)
{-# INLINEABLE any #-}
all :: forall a. (a -> Bool) -> BuiltinList a -> Bool
all :: forall a. (a -> Bool) -> BuiltinList a -> Bool
all a -> Bool
p = BuiltinList a -> Bool
go
where
go :: BuiltinList a -> Bool
go :: BuiltinList a -> Bool
go = Bool -> (a -> BuiltinList a -> Bool) -> BuiltinList a -> Bool
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList' Bool
True (\a
x BuiltinList a
xs -> if a -> Bool
p a
x then BuiltinList a -> Bool
go BuiltinList a
xs else Bool
False)
{-# INLINEABLE all #-}
(!!) :: forall a. BuiltinList a -> Integer -> a
!! :: forall a. BuiltinList a -> Integer -> a
(!!) BuiltinList a
xs0 Integer
i0
| Integer
i0 Integer -> Integer -> Bool
`B.lessThanInteger` Integer
0 = BuiltinString -> a
forall a. BuiltinString -> a
traceError BuiltinString
builtinListNegativeIndexError
| Bool
otherwise = BuiltinList a -> Integer -> a
go BuiltinList a
xs0 Integer
i0
where
go :: BuiltinList a -> Integer -> a
go :: BuiltinList a -> Integer -> a
go BuiltinList a
xs Integer
i =
(() -> () -> a)
-> (a -> BuiltinList a -> () -> a) -> BuiltinList a -> () -> a
forall a r.
(() -> r) -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
B.caseList
(\()
_ -> BuiltinString -> () -> a
forall a. BuiltinString -> a
traceError BuiltinString
builtinListIndexTooLargeError)
( \a
y BuiltinList a
ys ()
_ ->
if Integer
i Integer -> Integer -> Bool
`B.equalsInteger` Integer
0
then a
y
else BuiltinList a -> Integer -> a
go BuiltinList a
ys (Integer -> Integer -> Integer
B.subtractInteger Integer
i Integer
1)
)
BuiltinList a
xs
()