Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add firstJustMap, allJustMap #44

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 103 additions & 13 deletions src/Array/Extra.elm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module Array.Extra exposing
( all, any, member
( all, any, firstJustMap, member
, reverse, intersperse
, update, pop, removeAt, insertAt
, removeWhen, filterMap
, removeWhen, filterMap, allJustMap
, sliceFrom, sliceUntil, splitAt, unzip
, interweave, apply, map2, map3, map4, map5, zip, zip3
, resizelRepeat, resizerRepeat, resizelIndexed, resizerIndexed
Expand All @@ -14,7 +14,7 @@ module Array.Extra exposing

# observe

@docs all, any, member
@docs all, any, firstJustMap, member


# alter
Expand All @@ -25,7 +25,7 @@ module Array.Extra exposing

## filter

@docs removeWhen, filterMap
@docs removeWhen, filterMap, allJustMap


## part
Expand Down Expand Up @@ -179,20 +179,110 @@ filterMap tryMap =
\array ->
array
|> Array.foldr
(\el soFar -> soFar |> consTry (el |> tryMap))
(\el soFar -> soFar |> consJust (el |> tryMap))
[]
|> Array.fromList


consTry : Maybe a -> List a -> List a
consTry maybeNewHead =
\list ->
case maybeNewHead of
Just newHead ->
newHead :: list
consJust : Maybe a -> List a -> List a
consJust maybeNewHead =
case maybeNewHead of
Just newHead ->
\list -> list |> (::) newHead

Nothing ->
list
Nothing ->
identity


{-| After applying the given function to every element,
try unpacking _all_ `Just` values.
If just a single element is `Nothing`, `Nothing` is returned.

This is like a nicer [`all`](#all) where if you test for certain elements you already get
the `Array` with all the successful results or `Nothing` if one wasn't successful.

import Array exposing (empty, fromList)

empty
|> allJustMap String.toInt
--> Just empty

fromList [ "1", "2", "3" ]
|> allJustMap String.toInt
--> Just (fromList [ 1, 2, 3 ])

fromList [ "1", "NaN", "3" ]
|> allJustMap String.toInt
--> Nothing

This is often called "traverse".
A version with óut the map is often called "sequence"
and `Maybe.Extra` calls it [`combine`](https://package.elm-lang.org/packages/elm-community/maybe-extra/latest/Maybe-Extra#combineArray)

-}
allJustMap :
(element -> Maybe narrowElement)
-> Array element
-> Maybe (Array narrowElement)
allJustMap elementToMaybeValue =
\array ->
array
|> Array.foldr
(\element soFar ->
case soFar of
Nothing ->
Nothing

Just soFarList ->
Maybe.map
(\value -> soFarList |> (::) value)
(element |> elementToMaybeValue)
)
([] |> Just)
|> Maybe.map Array.fromList


{-| The first element (the one with lowest index) that returns a `Just` value for a given function.
If every element is transformed to `Nothing`, `Nothing` is returned.

This is like a nicer [`any`](#any) where if you test for certain elements you already get one
that matches your search.

import Array exposing (empty, fromList)

empty
|> firstJustMap String.toInt
--> Nothing

fromList [ "1", "2", "3" ]
|> firstJustMap String.toInt
--> Just 1

fromList [ "NaN", "2", "3" ]
|> firstJustMap String.toInt
--> Just 2

This is often called "findMap"
(for example in [`List.Extra`](https://package.elm-lang.org/packages/elm-community/list-extra/latest/List-Extra#findMap)).

-}
firstJustMap :
(element -> Maybe narrowElement)
-> Array element
-> Maybe narrowElement
firstJustMap elementToMaybeValue =
\array ->
array
|> Array.foldl
(\element soFar ->
case soFar of
Just found ->
found |> Just

Nothing ->
element |> elementToMaybeValue
)
Nothing


{-| Apply a given `Array` of changes to all elements.
Expand Down
38 changes: 38 additions & 0 deletions tests/Tests.elm
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,44 @@ suite =
)
)
]
, Test.describe "firstJustMap"
[ Test.fuzz (Fuzz.array (Fuzz.maybe Fuzz.int))
"is equivalent to filterMap |> get 0"
(\maybes ->
maybes
|> Array.firstJustMap identity
|> Expect.equal
(maybes
|> Array.filterMap identity
|> Array.get 0
)
)
]
, Test.describe "allJustMap"
[ Test.fuzz (Fuzz.array (Fuzz.map Just Fuzz.int))
"is equivalent to Just filterMap when only justs"
(\maybes ->
maybes
|> Array.allJustMap identity
|> Expect.equal
(maybes
|> Array.filterMap identity
|> Just
)
)
, Test.fuzz
(Fuzz.constant (\before after -> Array.append (before |> Array.push Nothing) after)
|> Fuzz.andMap (Fuzz.array (Fuzz.maybe Fuzz.int))
|> Fuzz.andMap (Fuzz.array (Fuzz.maybe Fuzz.int))
)
"is equivalent to Nothing when one Nothing"
(\maybes ->
maybes
|> Array.allJustMap identity
|> Expect.equal
Nothing
)
]
]


Expand Down