Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
标准Haskell函数::(a->;可能b)->;[a] ->;也许b_Haskell - Fatal编程技术网

标准Haskell函数::(a->;可能b)->;[a] ->;也许b

标准Haskell函数::(a->;可能b)->;[a] ->;也许b,haskell,Haskell,有一个标准函数if#返回函数在列表元素上的第一个成功应用(如果有的话,从左到右)。我希望Haskell中有这样的标准函数。我胡闹,什么也没找到 我是哈斯克尔的新手,我不确定什么是正确的方法。你会这样做吗: tryPick:: (a -> Maybe b) -> [a] -> Maybe b tryPick try xs = case Maybe.mapMaybe try xs of [] -> Nothing (x:_) -> Just x ?数据

有一个标准函数if#返回函数在列表元素上的第一个成功应用(如果有的话,从左到右)。我希望Haskell中有这样的标准函数。我胡闹,什么也没找到

我是哈斯克尔的新手,我不确定什么是正确的方法。你会这样做吗:

tryPick:: (a -> Maybe b) -> [a] -> Maybe b
tryPick try xs = case Maybe.mapMaybe try xs of
    [] -> Nothing
    (x:_) -> Just x

数据中的
列表可能是
函数。也许
看起来不错:

tryPick f = listToMaybe . mapMaybe f

这不一定是最简单的解决方案,但我觉得突出显示基于
的解决方案非常重要。我认为这是最漂亮的

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
这也可以立即推广到具有完全相同代码的任何可折叠的

tryPick :: Foldable t => (a -> Maybe b) -> t a -> Maybe b
Foldable
实例提供了使用
Monoid
s按顺序“粉碎”所有元素的方法。
第一个
幺半群
定义为

newtype First a = First { getFirst :: Maybe a }
是一个专门化的
mappend
操作,它只选择“第一个”或“最左边的”

所以,把它们放在一起,
getFirst。foldMap(First.f)
[a]
中的所有
a
s上计算你的
(a->Maybe b)
函数,然后将结果与“First”
仅赢的规则一起粉碎。

你想要:

tryPick :: (a -> Maybe b) -> [a] -> Maybe b
tryPick f as = msum (map f as)
我将解释这是如何工作的

map f as
生成一个可能的
操作列表,以尝试:

map f as :: [Maybe b]
msum
按顺序尝试它们,直到其中一个成功(返回值为
Just
)或全部失败(返回
Nothing
)。例如:

> msum [Nothing, Just 2, Just 3, Nothing]
Just 2
> msum [Nothing, Nothing]
Nothing
请注意,
msum
的类型更一般,因此我们可以将签名概括为:

tryPick :: (MonadPlus m) => (a -> m b) -> [a] -> m b

这将适用于任何
MonadPlus
。发现它对其他
MonadPlus
类型的功能会很有趣。

我参加派对有点晚了,但以下是J.Abrahamson使用Conor McBride可爱的
ala'
函数的答案:


这似乎有点神秘,但我发现它将“收集容器”(
First
)与“收集方案”(
foldMap
)以及与“预处理函数”(
a->Maybe b
)分离的方式——同时隐藏
newtype
包装和展开——相当漂亮<根据我的经验,code>ala
是创建漂亮代码的好工具,我想插上它。谢谢你,康纳

数据中的一个函数。可能已经可以处理您编写的情况。这会因为映射整个列表而导致额外的内存开销吗?我不确定GHC是否会在剩下的计算中创建thunk或优化它away@jozefg它在给定一个无限列表的情况下终止,所以直觉上这很好。@jozefg我想是的。心理内联我们会有
\(x:xs)->case(fx):tryPick fxs of{[]->Nothing;(y:\->Just y}
我知道它终止了,我很好奇这是否会产生额外的thunk或者它是否被优化掉了。这没什么大不了的,更多的是好奇。顺便说一句,对于比我更清晰的解决方案,这不是吗,在多个成功的应用程序上,返回一个公正的列表,而不是第一个成功的应用程序?
tryPick f=foldr(mplus.f)mzero::(MonadPlus m,Foldable t)=>(a->mb ta->mb
,两全其美!“从base 4.8.0.0开始,msum就是asum,专门针对MonadPlus。”我个人一直使用asum而不是msum。这是我很久以来看到的最棒的答案。我刚刚学到了一些非常有用的东西。谢谢
Alt
getAlt
First
getFirst
的更现代的替代方案。
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