Simple solution: find and join
It looks like you are looking for Data.List.find . find has a type signature
find :: (a -> Bool) -> [a] -> Maybe a
So you would do something like
result :: Maybe (Maybe String) result = find isJust [tryCombination xy | x <- [1..5], y <- [1..5]]
Or, if you don't want Maybe (Maybe String) (why do you need it?), You can stack them together with Control.Monad.join , which has a signature
join :: Maybe (Maybe a) -> Maybe a
so you have
result :: Maybe String result = join $ find isJust [tryCombination xy | x <- [1..5], y <- [1..5]]
More advanced solution: asum
If you want a slightly more advanced solution, you can use Data.Foldable.asum , which has a signature
asum :: [Maybe a] -> Maybe a
What he does is select the first Just value from the list of many. He does this using an Alternative instance of Maybe . An Alternative Maybe instance works as follows: (import Control.Applicative to access the <|> operator)
λ> Nothing <|> Nothing Nothing λ> Nothing <|> Just "world" Just "world" λ> Just "hello" <|> Just "world" Just "hello"
In other words, he selects the first Just value from two alternatives. Imagine putting <|> between each item in your list so that
[Nothing, Nothing, Just "okay", Nothing, Nothing, Nothing, Just "okay"]
goes into
Nothing <|> Nothing <|> Just "okay" <|> Nothing <|> Nothing <|> Nothing <|> Just "okay"
This is exactly what the asum function does! Since <|> is short-circuited, it will only evaluate to the first Just value. At the same time, your function will be as simple as
result :: Maybe String result = asum [tryCombination xy | x <- [1..5], y <- [1..5]]
Why do you need this more advanced solution? It is not only shorter; once you know the idiom (i.e. when you are familiar with Alternative and asum ), it’s much more clear what the function does by simply reading the first few characters of the code.