diff --git a/compiler/damlc/daml-stdlib-src/DA/NonEmpty.daml b/compiler/damlc/daml-stdlib-src/DA/NonEmpty.daml index 73e0459bffc9..0ca74dc2ff85 100644 --- a/compiler/damlc/daml-stdlib-src/DA/NonEmpty.daml +++ b/compiler/damlc/daml-stdlib-src/DA/NonEmpty.daml @@ -13,12 +13,15 @@ -- ``` module DA.NonEmpty ( NonEmpty(..) + , cons , append , map , nonEmpty , singleton , toList , reverse + , find + , delete , foldl1 , foldr1 , foldr @@ -29,7 +32,7 @@ module DA.NonEmpty , foldl1A ) where -import Prelude hiding (reverse, foldr, foldl, one, map) +import Prelude hiding (cons, reverse, find, foldr, foldl, one, map) import Prelude qualified as P import DA.Foldable qualified as F import DA.NonEmpty.Types @@ -73,6 +76,10 @@ instance F.Foldable NonEmpty where instance T.Traversable NonEmpty where mapA f l = liftA2 NonEmpty (f l.hd) (T.mapA f l.tl) +-- | Prepend an element to a non-empty list. +cons : a -> NonEmpty a -> NonEmpty a +cons a ne = NonEmpty a (ne.hd :: ne.tl) + -- | Append or concatenate two non-empty lists. append : NonEmpty a -> NonEmpty a -> NonEmpty a append l r = NonEmpty l.hd (l.tl ++ toList r) @@ -99,6 +106,28 @@ toList (NonEmpty head tail) = head :: tail reverse : NonEmpty a -> NonEmpty a reverse l = let hd::tl = L.reverse $ toList l in NonEmpty with hd; tl +-- | Find an element in a non-empty list. +find : (a -> Bool) -> NonEmpty a -> Optional a +find p (NonEmpty head tail) + | p head = Some head + | otherwise = L.find p tail + +-- | The 'deleteBy' function behaves like 'delete', but takes a +-- user-supplied equality predicate. +deleteBy : (a -> a -> Bool) -> a -> NonEmpty a -> [a] +deleteBy eq a n@(NonEmpty head []) + | head `eq` a = [] + | otherwise = [head] +deleteBy eq a (NonEmpty head (t::ts)) + | head `eq` a = t::ts + | t `eq` a = head::ts + | otherwise = head :: t :: L.deleteBy eq a ts + +-- | Remove the first occurence of x from the non-empty list, potentially +-- removing all elements. +delete : Eq a => a -> NonEmpty a -> [a] +delete = deleteBy (==) + -- | Apply a function repeatedly to pairs of elements from a non-empty list, -- from the left. For example, `foldl1 (+) (NonEmpty 1 [2,3,4]) = ((1 + 2) + 3) + 4`. foldl1 : (a -> a -> a) -> NonEmpty a -> a diff --git a/compiler/damlc/tests/daml-test-files/NonEmpty.daml b/compiler/damlc/tests/daml-test-files/NonEmpty.daml index 5d8ac22cf8c3..36690f5b5d70 100644 --- a/compiler/damlc/tests/daml-test-files/NonEmpty.daml +++ b/compiler/damlc/tests/daml-test-files/NonEmpty.daml @@ -4,8 +4,9 @@ module NonEmpty where -import DA.NonEmpty +import Prelude hiding (cons, find) import DA.Assert +import DA.NonEmpty testApplicative = scenario do let l = NonEmpty 1 [2, 3, 4] @@ -22,3 +23,26 @@ testOrd = scenario do compare (NonEmpty 1 []) (NonEmpty 1 [0]) === LT compare (NonEmpty 1 [0]) (NonEmpty 1 [0]) === EQ compare (NonEmpty 1 [0]) (NonEmpty 1 [1]) === LT + +testCons = scenario do + cons "a" (NonEmpty "b" []) === NonEmpty "a" ["b"] + +testFind = scenario do + find (== 1) (NonEmpty 0 []) === None + find (== 1) (NonEmpty 1 []) === Some 1 + find (== 1) (NonEmpty 0 [1]) === Some 1 + find (== 1) (NonEmpty 0 [0]) === None + find (== 1) (NonEmpty 0 [1, 2]) === Some 1 + find (== 1) (NonEmpty 0 [2, 1]) === Some 1 + find (== 1) (NonEmpty 0 [1, 2, 1]) === Some 1 + +testDelete = scenario do + delete 1 (NonEmpty 0 []) === [0] + delete 1 (NonEmpty 1 []) === [] + delete 1 (NonEmpty 0 [1]) === [0] + delete 1 (NonEmpty 0 [0]) === [0, 0] + delete 1 (NonEmpty 1 [0]) === [0] + delete 1 (NonEmpty 0 [1, 2]) === [0, 2] + delete 1 (NonEmpty 0 [2, 1]) === [0, 2] + delete 1 (NonEmpty 0 [1, 2, 1]) === [0, 2, 1] +