如果F#返回第一个(从左到右,如果有的话)在列表元素上成功应用函数,则有一个标准的tryPick函数.我正在跳跃有一个像Haskell那样的标准函数.我试过 Hoogle并没有找到任何东西.
我是Haskell的新手,我不确定这样做的正确方法是什么.你会这样做:
tryPick:: (a -> Maybe b) -> [a] -> Maybe b
tryPick try xs = case Maybe.mapMaybe try xs of
[] -> Nothing
(x:_) -> Just x
Run Code Online (Sandbox Code Playgroud)
?
Gab*_*lez 15
你要:
tryPick :: (a -> Maybe b) -> [a] -> Maybe b
tryPick f as = msum (map f as)
Run Code Online (Sandbox Code Playgroud)
我将解释它是如何工作的.
map f as生成可能的Maybe操作列表:
map f as :: [Maybe b]
Run Code Online (Sandbox Code Playgroud)
msum按顺序尝试它们直到成功(将值作为a返回Just)或者它们都失败(返回a Nothing).例如:
> msum [Nothing, Just 2, Just 3, Nothing]
Just 2
> msum [Nothing, Nothing]
Nothing
Run Code Online (Sandbox Code Playgroud)
请注意,msum类型更通用,因此我们可以将签名概括为:
tryPick :: (MonadPlus m) => (a -> m b) -> [a] -> m b
Run Code Online (Sandbox Code Playgroud)
这将适用于任何人MonadPlus.玩得开心,发现它对其他MonadPlus类型的作用.
Jos*_*Lee 14
该listToMaybe函数Data.Maybe看起来很不错:
tryPick f = listToMaybe . mapMaybe f
Run Code Online (Sandbox Code Playgroud)
J. *_*son 12
它不一定是最简单的解决方案,但我认为突出First Monoid基于解决方案很重要.我认为这是最漂亮的.
import Data.Monoid
import Data.Foldable (Foldable, foldMap)
tryPick :: (a -> Maybe b) -> [a] -> Maybe b
tryPick f = getFirst . foldMap (First . f) -- this is just `foldMap f`
-- with the "firsty" Maybe Monoid
Run Code Online (Sandbox Code Playgroud)
对于Foldable具有完全相同代码的任何一个,这也可以立即推广
tryPick :: Foldable t => (a -> Maybe b) -> t a -> Maybe b
Run Code Online (Sandbox Code Playgroud)
Foldable实例提供了使用Monoids 将所有元素"粉碎"在一起的方法.该First Monoid定义为
newtype First a = First { getFirst :: Maybe a }
Run Code Online (Sandbox Code Playgroud)
是一个选择"第一"或"最左" Maybe的mappend操作的专业化Just.
因此,将它们放在一起,getFirst . foldMap (First . f)计算你(a -> Maybe b)对所有as中的函数[a],然后将结果与"第一" Just获胜的规则一起打破.
我来参加派对有点晚了,但这里有一个关于J. Abrahamson回答的变体,它使用了Conor McBride ala'在newtype套装中的可爱功能:
import Control.Newtype (ala')
import Data.Foldable (Foldable, foldMap)
import Data.Monoid (First(..))
tryPick :: (Foldable t) => (a -> Maybe b) -> t a -> Maybe b
tryPick = ala' First foldMap
Run Code Online (Sandbox Code Playgroud)
这看起来有点神秘,但我发现它将"收集容器"(First)从"收集方案"(foldMap)和"预处理功能"(a -> Maybe b)中解耦- 同时隐藏newtype包装和展开 - 而不是美丽.ala我的经验是创建漂亮代码的好工具,我想插上它.谢谢,康纳!