Skip to content

Commit

Permalink
Optimize mapOptional and add more efficient findOptional (#9214)
Browse files Browse the repository at this point in the history
* Optimize mapOptional and add more efficient findOptional

Given that we don’t have list fusion catOptionals . map f is clearly
less efficient than this version.

I also added findOptional which can be pretty handy in certain cases.

changelog_begin
changelog_end

* more foldr

changelog_begin
changelog_end

* fix tests

changelog_begin
changelog_end
  • Loading branch information
cocreature committed Mar 23, 2021
1 parent 1e0c67c commit 90c5ce7
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
16 changes: 15 additions & 1 deletion compiler/damlc/daml-stdlib-src/DA/Optional.daml
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,24 @@ isNone = not . isSome
-- the result list. If it is `Some b`, then `b` is included in the
-- result list.
mapOptional : (a -> Optional b) -> [a] -> [b]
mapOptional f = catOptionals . map f
mapOptional p = foldr f []
where f x acc = case p x of
None -> acc
Some y -> y :: acc

-- | Perform some operation on `Some`, given the field inside the
-- `Some`.
whenSome : Applicative m => Optional a -> (a -> m ()) -> m ()
whenSome None _ = pure ()
whenSome (Some v) f = f v

-- | The `findOptional` returns the value of the predicate at the first
-- element where it returns `Some`. `findOptional` is similar to `find` but it
-- allows you to return a value from the predicate. This is useful both as a more
-- type safe version if the predicate corresponds to a pattern match
-- and for performance to avoid duplicating work performed in the predicate.
findOptional : (a -> Optional b) -> [a] -> Optional b
findOptional _ [] = None
findOptional p (x :: xs) = case p x of
None -> findOptional p xs
Some y -> Some y
10 changes: 10 additions & 0 deletions compiler/damlc/tests/daml-test-files/Optional.daml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,13 @@ testWhenSome = scenario do
submit p (fetch cid)
whenSome (Some 5) (\x -> submit p $ exercise cid $ ConsumeIfPositive x cid)
submitMustFail p (fetch cid)

testFindOptional = scenario do
findOptional toLeft [] === (None : Optional ())
findOptional toLeft [Right 1] === (None : Optional ())
findOptional toLeft [Right 1, Left 2] === Some 2
findOptional toLeft [Right 1, Left 2, Left 3] === Some 2

toLeft : Either a b -> Optional a
toLeft (Left a) = Some a
toLeft (Right _) = None

0 comments on commit 90c5ce7

Please sign in to comment.