EDIT: original title was “Looking for a function similar to Maybe.map2”
Hello!
I’m implementing a “Temperature Converter” as an exercise, see: 7GUIs.
I’m bothered by this warnOnInvalidInput function:
I would like to remove the duplication and collapse the logic such that returning an empty node is specified only once.
Regarding the function I’m looking, I notice that its “shape” is similar to Maybe.map2. But I need the inverse logic on the second branch.
map2 : (a -> b -> value) -> Maybe a -> Maybe b -> Maybe value
map2 func ma mb =
case ma of
Nothing ->
Nothing
Just a ->
case mb of
Nothing ->
Nothing
Just b ->
Just (func a b)
I’m interested in improving at recognizing patterns so I’m wondering if such a function exists?
Failing that, would you have a suggestion to improve this function? I’m thinking I may be missing something here.
I would leave it as is. If you try and shorten it more I fear you might make it more difficult to read later. It definitely is similar to Maybe.map2, but because you’re inversing the second Maybe I feel like that helper function would be complex to understand.
One simple change to your code would be to assign the “default result” to a variable and reuse that? That would at least indicate your intention of having the same value in these two out of three branches?
Rather than trying to combine all of the logic into one operator, I would probably factor out each piece into is own function and use a pipeline. Something like this:
warnOnInvalidInput : String -> Maybe String -> Html msg
warnOnInvalidInput name ms =
ms
|> Maybe.Extra.filter isNotBlank
|> Maybe.Extra.filter isInvalid
|> Maybe.Extra.isJust
|> warningMessage name
warningMessage : String -> Bool -> Html msg
warningMessage name invalidInput =
if invalidInput then
p [] [ text ("Invalid " ++ name ++ " input") ]
else
text ""
isNotBlank : String -> Bool
isNotBlank s =
if String.trim s == "" then
False
else
True
isInvalid : String -> Bool
isInvalid s =
case String.toFloat s of
Nothing ->
True
Just _ ->
False
warnOnInvalidInput : String -> Maybe String -> Html msg
warnOnInvalidInput name ms =
let
noErrorNode =
text ""
errorNode =
p [] [ text ("Invalid " ++ name ++ " input") ]
in
case Maybe.andThen toNothingIfBlank ms of
Nothing ->
noErrorNode
Just s ->
case String.toFloat s of
Nothing ->
errorNode
Just _ ->
noErrorNode
Maybe that change is too obvious or not worth it. I’m not even sure i would’ve coded it like that .