-
-
Save shamansir/281b35e117e601d232d28130250569c7 to your computer and use it in GitHub Desktop.
iterateMap, iterateOr, iterateAnd, iterateMapAnd, iterateWhileAnd in Elm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module UtilsTest exposing (suite) | |
import Test exposing (..) | |
import Expect | |
import Utils exposing (..) | |
suite : Test | |
suite = | |
describe "utils" | |
[ testReduce | |
, testIterateMap | |
, testIterateOr | |
, testIterateAnd | |
, testIterateMapAnd | |
, testIterateWhileAnd | |
] | |
testReduce : Test | |
testReduce = | |
describe "reduce" | |
[ test "should iterate through a list while function returns something" <| | |
(\() -> | |
Expect.equal | |
3 | |
(reduce -1 [ 0, 1, 2, 3 ] | |
(\n _ -> Just n)) | |
) | |
, test "should stop when function returns `Nothing`" <| | |
(\() -> | |
Expect.equal | |
1 | |
(reduce -1 [ 0, 1, 2, 3 ] | |
(\n _ -> if n < 2 then Just n else Nothing)) | |
) | |
, test "should return initial value when first element returned nothing" <| | |
(\() -> | |
Expect.equal | |
-1 | |
(reduce -1 [ 0, 1, 2, 3 ] (\_ _ -> Nothing) ) | |
) | |
, test "should be able to join items" <| | |
(\() -> | |
Expect.equal | |
5 | |
(reduce -1 [ 0, 1, 2, 3 ] | |
(\n prevN -> Just (n + prevN))) | |
) | |
, test "should provide access to previous items" <| | |
(\() -> | |
Expect.equal | |
[ 1, 2, 3, 4 ] | |
(reduce [] [ 0, 1, 2, 3 ] | |
(\n prev -> Just (prev ++ [ n + 1 ]))) | |
) | |
, test "should work with strings" <| | |
(\() -> | |
Expect.equal | |
"3/2/1/0/" | |
(reduce "" [ 0, 1, 2, 3 ] | |
(\n prev -> Just (toString n ++ "/" ++ prev))) | |
) | |
] | |
testIterateMap : Test | |
testIterateMap = | |
describe "iterateMap" | |
[ test "should be able to get all elements while function returns something" <| | |
(\() -> | |
Expect.equal | |
[ 0, 1, 2, 3 ] | |
(iterateMap (\n -> Just n) [ 0, 1, 2, 3 ]) | |
) | |
, test "should apply what mapping function returns" <| | |
(\() -> | |
Expect.equal | |
[ 10, 11, 12, 13 ] | |
(iterateMap (\n -> Just (n + 10)) [ 0, 1, 2, 3 ]) | |
) | |
, test "should stop when mapping function returns `Nothing`" <| | |
(\() -> | |
Expect.equal | |
[ 0, 1 ] | |
(iterateMap | |
(\n -> if (n < 2) then Just n else Nothing ) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return empty array when function returned `Nothing` for the first element" <| | |
(\() -> | |
Expect.equal | |
[ ] | |
(iterateMap | |
(\n -> if (n < 0) then Just n else Nothing ) | |
[ 0, -1, -2, -3 ]) | |
) | |
, test "should apply mapping function despite being stopped by `Nothing`" <| | |
(\() -> | |
Expect.equal | |
[ -10, -9, -8 ] | |
(iterateMap | |
(\n -> if (n < 3) then Just (n - 10) else Nothing ) | |
[ 0, 1, 2, 3 ]) | |
) | |
] | |
testIterateOr : Test | |
testIterateOr = | |
describe "iterateOr" | |
[ test "should get first element for which function returns something" <| | |
(\() -> | |
Expect.equal | |
(Just 0) | |
(iterateOr (\n -> Just n) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should get first element for which function returns something, p.II" <| | |
(\() -> | |
Expect.equal | |
(Just 2) | |
(iterateOr (\n -> if (n > 1) then Just n else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should apply what mapping function returns" <| | |
(\() -> | |
Expect.equal | |
(Just 12) | |
(iterateOr (\n -> if (n > 1) then Just (n + 10) else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function returned `Nothing` for all the elements" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateOr | |
(\n -> if (n > 10) then Just n else Nothing ) | |
[ 0, 1, 2, 3 ]) | |
) | |
] | |
testIterateAnd : Test | |
testIterateAnd = | |
describe "iterateAnd" | |
[ test "should return last successful element when function passes for all of them" <| | |
(\() -> | |
Expect.equal | |
(Just 3) | |
(iterateAnd (\n -> Just n) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function not passes for one of the elements" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateAnd (\n -> if (n > 0) then Just n else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should apply what mapping function returns" <| | |
(\() -> | |
Expect.equal | |
(Just 13) | |
(iterateAnd (\n -> if (n > 1) then Just (n + 10) else Just (n - 10)) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function returned `Nothing` for all the elements" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateAnd | |
(\n -> if (n > 10) then Just n else Nothing ) | |
[ 0, 1, 2, 3 ]) | |
) | |
] | |
testIterateMapAnd : Test | |
testIterateMapAnd = | |
describe "iterateMapAnd" | |
[ test "should return all values when function passes for all the elements" <| | |
(\() -> | |
Expect.equal | |
(Just [ 0, 1, 2, 3 ]) | |
(iterateMapAnd (\n -> Just n) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function not passes for one of the elements" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateMapAnd (\n -> if (n > 0) then Just n else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function not passes for one of the elements, p. II" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateMapAnd (\n -> if (n < 3) then Just n else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should apply what mapping function returns" <| | |
(\() -> | |
Expect.equal | |
(Just [ -10, -9, 12, 13 ]) | |
(iterateMapAnd (\n -> if (n > 1) then Just (n + 10) else Just (n - 10)) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function returned `Nothing` for all the elements" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateMapAnd | |
(\n -> if (n > 10) then Just n else Nothing ) | |
[ 0, 1, 2, 3 ]) | |
) | |
] | |
testIterateWhileAnd : Test | |
testIterateWhileAnd = | |
describe "iterateWhileAnd" | |
[ test "should return last successful element when function passes for all of them" <| | |
(\() -> | |
Expect.equal | |
(Just 3) | |
(iterateWhileAnd (\n -> Just n) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when success chain in not bound to the start of the list" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateWhileAnd (\n -> if (n > 0) then Just n else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return last element from the continuous chain of successes" <| | |
(\() -> | |
Expect.equal | |
(Just 2) | |
(iterateWhileAnd (\n -> if (n < 3) then Just n else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should apply what mapping function returns" <| | |
(\() -> | |
Expect.equal | |
(Just 12) | |
(iterateWhileAnd (\n -> if (n < 3) then Just (n + 10) else Nothing) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should apply what mapping function returns, p. II" <| | |
(\() -> | |
Expect.equal | |
(Just 13) | |
(iterateWhileAnd (\n -> if (n > 1) then Just (n + 10) else Just (n - 10)) | |
[ 0, 1, 2, 3 ]) | |
) | |
, test "should return `Nothing` when function returned `Nothing` for all the elements" <| | |
(\() -> | |
Expect.equal | |
Nothing | |
(iterateWhileAnd | |
(\n -> if (n > 10) then Just n else Nothing ) | |
[ 0, 1, 2, 3 ]) | |
) | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Utils exposing (..) | |
import Tuple exposing (first) | |
import List exposing (foldl) | |
reduce : b -> List a -> (a -> b -> Maybe b) -> b | |
reduce init src reducer = | |
Tuple.first | |
(List.foldl | |
(\curVal (prevVal, prevContinue) -> | |
case prevContinue of | |
True -> case (reducer curVal prevVal) of | |
Just v -> (v, True) | |
Nothing -> (prevVal, False) | |
False -> (prevVal, False)) | |
(init, True) | |
src) | |
-- executes the function for every item of `List a`, and while this | |
-- function returns `Just b`, add `b` instance to a resulting list, | |
-- but stops execution immediately when function returns `Nothing` for | |
-- the first time. | |
-- | |
-- Example: | |
-- | |
-- ``` | |
-- (iterateMap | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 2, 1, 0, 1, 3, 5, 1, 0, 2, 3 ]) | |
-- -> [ 102, 103, 100, 101, 103 ] | |
-- | |
-- (iterateMap | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 5, 2, 1, 0, 1, 3, 1, 0, 2, 3 ]) | |
-- -> [ ] | |
-- ``` | |
iterateMap : (a -> Maybe b) -> List a -> List b | |
iterateMap f src = | |
reduce [] src | |
(\cur allValues -> | |
case (f cur) of | |
Just nextValue -> Just ( allValues ++ [ nextValue ] ) | |
Nothing -> Nothing | |
) | |
-- execute the function for every item of `List a`, and when this | |
-- function returns `Just b` for the first time, return this `b` and | |
-- stop execution. | |
-- | |
-- Example: | |
-- | |
-- ``` | |
-- (iterateOr | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 5, 2, 1, 0, 1, 3, 1, 0, -1, 3 ]) | |
-- -> Just 102 | |
-- | |
-- (iterateOr | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 5, 7, 15, 12, 10, 24, 4, 6, 28 ]) | |
-- -> Nothing | |
-- ``` | |
iterateOr : (a -> Maybe b) -> List a -> Maybe b | |
iterateOr f src = | |
reduce Nothing src | |
(\cur hasValue -> | |
case hasValue of | |
Just v -> Just hasValue | |
Nothing -> case (f cur) of | |
Just v -> Just ( Just v ) | |
Nothing -> Just Nothing | |
) | |
-- execute the function for every item of `List a`, return the last | |
-- succesful result only when the function returned `Just a` for all | |
-- the items from the list with no exceptions, else return `Nothing`. | |
-- | |
-- Example: | |
-- | |
-- ``` | |
-- (iterateAnd | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 2, 1, 0, 1, 3 ]) | |
-- -> Just 103 | |
-- | |
-- (iterateAnd | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 2, 1, 0, 1, 5 ]) | |
-- -> Nothing | |
-- ``` | |
iterateAnd : (a -> Maybe b) -> List a -> Maybe b | |
iterateAnd f src = | |
Tuple.second | |
(reduce ( True, Nothing ) src | |
(\cur ( hasValue, _ ) -> | |
case hasValue of | |
True -> case (f cur) of | |
Just v -> Just ( True, Just v ) | |
Nothing -> Just ( False, Nothing ) | |
False -> Just ( False, Nothing ) | |
) | |
) | |
-- execute the function for every item of `List a`, return all the | |
-- collected results only when the function returned `Just a` for all | |
-- the items from the list with no exceptions, else return `Nothing`. | |
-- | |
-- Example: | |
-- | |
-- ``` | |
-- (iterateMapAnd | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 2, 1, 0, 1, 3 ]) | |
-- -> Just [ 102, 101, 100, 101, 103 ] | |
-- | |
-- (iterateMapAnd | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 2, 1, 0, 1, 5 ]) | |
-- -> Nothing | |
-- ``` | |
iterateMapAnd : (a -> Maybe b) -> List a -> Maybe (List b) | |
iterateMapAnd f src = | |
Tuple.second | |
(reduce ( True, Nothing ) src | |
(\cur ( hasValue, maybeAllValues ) -> | |
case hasValue of | |
True -> case (f cur) of | |
Just nextValue -> | |
case maybeAllValues of | |
Just allValues -> Just ( True, Just ( allValues ++ [ nextValue ] ) ) | |
Nothing -> Just ( True, Just [ nextValue ] ) | |
Nothing -> Just ( False, Nothing ) | |
False -> Just ( False, Nothing ) | |
) | |
) | |
-- execute the function for every item of `List a`, and while this | |
-- function returns `Just b`, keeps last successful `b` instance to return, | |
-- but stop execution immediately when function returns `Nothing` for | |
-- the first time. | |
-- | |
-- Example: | |
-- | |
-- ``` | |
-- (iterateWhileAnd | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 2, 1, 0, 1, 3, 5, 1, 0, 2, -1 ]) | |
-- -> Just 103 | |
-- | |
-- (iterateWhileAnd | |
-- (\n -> if (n <= 3) then Just (n + 100) else Nothing) | |
-- [ 5, 2, 1, 0, 1, 3, 1, 0, 2, 3 ]) | |
-- -> Nothing | |
-- ``` | |
iterateWhileAnd : (a -> Maybe b) -> List a -> Maybe b | |
iterateWhileAnd f src = | |
Tuple.second | |
(reduce ( True, Nothing ) src | |
(\cur ( hasValue, maybeLastValue ) -> | |
case hasValue of | |
True -> case (f cur) of | |
Just v -> Just ( True, Just v ) | |
Nothing -> case maybeLastValue of | |
Just lastValue -> Just ( False, Just lastValue ) | |
Nothing -> Just ( False, Nothing ) | |
False -> Just ( False, Nothing ) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment