如何应用在Haskell中工作的第一个部分函数?

use*_*553 9 haskell

假设我有一个列表fns的从部分功能ab,我所代表的功能从aMaybe b,并且我有一个对象x类型的a.假设现在我要定义另一个函数从aMaybe b这需要第一的价值f x,是不是Nothing,如果这样的f存在fns,或价值Nothing,如果没有这样的f存在.所以基本上它f x是第一个f有效的输出,或者Nothing如果没有f效果.

提出一些能够完成这项工作的代码并不难.例如,可以创建一个列表从中[f x| f <- fns]删除所有Nothings,然后取结果列表的头部,或者Nothing如果该列表为空.但这感觉很笨拙,这似乎是一种普遍的情况,在Haskell中使用一些内置函数可以实现更加时尚的实现.如果是这样,那么我有兴趣知道它是什么.

Ale*_*lec 12

Alternative是为了什么.它代表选择,在这里您可以选择Maybe值.你可以做点什么

foldr (<|>) empty [f x | f <- fns]
Run Code Online (Sandbox Code Playgroud)

Data.Foldable你也有asum :: (Foldable t, Alternative f) => t (f a) -> f a更直接地做你想要的东西:

asum [f x | f <- fns]
Run Code Online (Sandbox Code Playgroud)

作为旁注,我应该注意到它MonadPlus也为你的Maybe实例做了你想要的.如上所述,你可以拥有

foldr mplus mempty [f x | f <- fns]
Run Code Online (Sandbox Code Playgroud)

msum [f x | f <- fns]
Run Code Online (Sandbox Code Playgroud)

但你应该Alternative在这里使用IMO ,因为它更准确地传达了你的"选择"的含义.

  • 我确实考虑过`($ x)<$> fns`但我认为使用基于`$`的运算符来做两件不同的事情对于那些不熟悉正在发生的事情的人来说会更加混乱. (2认同)

pig*_*ker 9

Data.Monoid,被称为"一开始"行为的newtype副本.MaybeFirstJust

如果您正在寻找类型的功能

[a -> First b] -> a -> First b
Run Code Online (Sandbox Code Playgroud)

根据你描述的行为,它就是这样

fold
Run Code Online (Sandbox Code Playgroud)

from Data.Foldable,因为monoid行为a ->需要逐点提升:Monoidfor a -> First b正好选择了第一个应用结果.可悲的是(因为我的眼泪已经很多了),Maybe而不是First需要多做一些工作.

请注意,逐点提升,a ->通过[],只是那种工作sequenceA,所以

(asum .) . sequenceA
Run Code Online (Sandbox Code Playgroud)

会做的.

从类型中获取需要提示的monoid结构是很好的:在这种情况下,访问Alternative行为asum必须要做.

  • @BenjaminHodgson,它在`base`中,并且将成为`Monoid`的超类,但这并不会让那些打扰了Pigworker.他想要`可折叠的可能'的'First`语义,但不能得到它们. (3认同)