简单的解决方案:find
and join
看起来您正在寻找Data.List.find http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-List.html#v:find. find
具有类型签名
find :: (a -> Bool) -> [a] -> Maybe a
所以你会做类似的事情
result :: Maybe (Maybe String)
result = find isJust [tryCombination x y | x <- [1..5], y <- [1..5]]
或者,如果您不想要Maybe (Maybe String)
(为什么要这样做?),你可以将它们折叠在一起Control.Monad.join http://hackage.haskell.org/package/base-4.8.0.0/docs/Control-Monad.html#v:join,其中有签名
join :: Maybe (Maybe a) -> Maybe a
这样你就有了
result :: Maybe String
result = join $ find isJust [tryCombination x y | x <- [1..5], y <- [1..5]]
更高级的解决方案:asum
如果您想要稍微高级的解决方案,您可以使用Data.Foldable.asum https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-Foldable.html,其中有签名
asum :: [Maybe a] -> Maybe a
它的作用是选择第一个Just
从许多列表中获取价值。它通过使用Alternative
的实例Maybe
. The Alternative
的实例Maybe
工作原理如下:(导入Control.Applicative
访问<|>
操作员)
λ> Nothing <|> Nothing
Nothing
λ> Nothing <|> Just "world"
Just "world"
λ> Just "hello" <|> Just "world"
Just "hello"
换句话说,它选择第一个Just
两种选择的价值。想象一下放<|>
在列表的每个元素之间,这样
[Nothing, Nothing, Just "okay", Nothing, Nothing, Nothing, Just "okay"]
被转向
Nothing <|> Nothing <|> Just "okay" <|> Nothing <|> Nothing <|> Nothing <|> Just "okay"
这正是asum
功能确实如此!自从<|>
是短路的,它只会评估第一个Just
价值。有了这个,你的功能就会很简单
result :: Maybe String
result = asum [tryCombination x y | x <- [1..5], y <- [1..5]]
您为什么需要这种更先进的解决方案?它不仅更短,而且更短。一旦你知道了这个习语(即当你熟悉Alternative
and asum
)只需阅读代码的前几个字符,就可以更清楚该函数的作用。