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

如何应用在Haskell中工作的第一个分部函数?,haskell,Haskell,假设我有一个从a到b的部分函数列表fns,我将其表示为从a到可能是b的函数,并且我有一个x类型的对象a。假设现在我想定义另一个从a到的函数,可能b取第一个fx的值,该值不是Nothing,如果在fns中存在这样的f,或者如果不存在这样的f值。因此,基本上,它为第一个工作的f输出fx,或者如果没有f工作,则输出Nothing 想出一些代码来完成这项工作并不难。例如,您可以创建一个列表[fx | f,这就是它的用途。它代表选择,在这里,您可以在也许值之间进行选择。您可以执行以下操作 foldr (&

假设我有一个从
a
b
的部分函数列表
fns
,我将其表示为从
a
可能是b
的函数,并且我有一个
x
类型的对象
a
。假设现在我想定义另一个从
a
的函数,可能b
取第一个
fx
的值,该值不是
Nothing
,如果在
fns
中存在这样的
f
,或者如果不存在这样的
f
值。因此,基本上,它为第一个工作的
f
输出
fx
,或者如果没有
f
工作,则输出
Nothing

想出一些代码来完成这项工作并不难。例如,您可以创建一个列表
[fx | f,这就是它的用途。它代表选择,在这里,您可以在
也许
值之间进行选择。您可以执行以下操作

foldr (<|>) empty [f x | f <- fns]

作为附带说明,我应该注意到,它也可以满足您对其
实例的要求

foldr mplus mempty [f x | f <- fns]

foldr mplus mempty[f x | f在
数据.Monoid
中,一个名为
First
newtype
副本可能具有“先取
刚取
”行为

如果您正在寻找类型为的函数

[a -> First b] -> a -> First b
就你所描述的行为而言,它只是

fold
Data.Foldable
,因为
a->
的幺半群行为完成了所需的逐点提升:
a->First b
幺半群正是挑选第一个有效的应用程序结果。可悲的是(我为此流泪了很多),要获得
可能
而不是
首先
需要更多的工作

请注意,点式提升,即通过
[]
拉出
a->
,正是
sequenceA
的工作类型,因此

(asum .) . sequenceA
我会做好的

从类型中获得所需的幺半群结构是很好的:在这种情况下,使用
asum
访问
可选的
行为将不得不这样做。

警告:这是一个非常非标准的解决方案。但我个人非常喜欢它的优雅和潜在的思维扭曲

在上,您可以找到一个名为
swing
的函数。它的实现和类型起初很混乱:

swing::(((a->b)->b)->c->d)->c->a->d)
swing=flip.(.flip id)
当您看到它的完全应用形式时,您可以首先了解它的功能:

swing f c a=f($a)c
结合其他高阶函数,它所做的事情看起来几乎像魔术。链接中的示例:

swing-map::[a->b]->a->[b]
任意摆动::[a->Bool]->a->Bool
swing foldr::b->a->[a->b->b]->b
摆动zipWith::[a->b->c]->a->[b]->[c]
swing find::[a->Bool]->a->Maybe(a->Bool)
swing分区::[a->Bool]->a->([a->Bool],[a->Bool])
所有这些函数都完全按照您从类型中假定的那样执行。(但请注意,wiki有点过时。到目前为止,这些函数中的大多数自动适用于任何
可折叠的
类型。)

您可以从搜索的函数开始

swing mapMaybe::[a->Maybe b]->a->[b]
然后将
列表应用到Maybe
(两个函数都来自
数据。可能是

更一般的形式是

swing-mapM::(单子m,可遍历的t)=>t(a->mb)->a->m(tb)
因此,例如(使用
classyprellude
以获得完全的通用性,同时以一些约束噪声为代价,使用
headMay
作为
listToMaybe
的更通用形式):

f::(可遍历的t,单折叠的(tb),元素(tb)~b)
=>t(a->Maybe b)->a->Maybe b
f函数x=连接$headMay swing mapM函数x

是的,这可能会让你的头变成糊状——但这就像是只有全神贯注地低头看一个微笑。

asum
在基础中,在
数据中。可折叠的
。使用profunctors包,你还可以编写
runStar.asum.fmap Star
,这要感谢
备选方案f=>备选方案(Star f a)与代码理解相比,我认为 map($x)FNS比较好。“AgOLL或AHEM,<代码> SCONSENEA FNS X< /代码>由于函数(“Reader”)的应用。我确实考虑过<代码>(x)。fns
但我认为使用基于
$
的运算符来做两件不同的事情,对于不熟悉发生了什么的人来说会显得更加困惑。你知道是否有计划将
半群
引入
,这样我们就可以放松
幺半群(可能是a)
的超类约束,并且有一个实例不会让成年男人流泪?@BenjaminHodgson你可能会喜欢。@BenjaminHodgson,它在
基中,将是
幺半群的超类,但这并不是困扰猪倌的原因。他首先想要
语义,而
可能是可折叠的
,并且无法得到它em.dfeuer关于我在这种情况下想要什么是正确的。使“提升
半群
幺半群
可能无法解决上述问题。我认为提升
半群
应该有一个完全不同的类型:它的原始数据表示可能与
可能
的原始数据表示相同,但类型类机制为我们获取有用设备的方式意味着在Haskell中,当我们命名一个类型时,我们不仅要命名数据表示,还要命名隐式关联的结构。
可能是用于故障传播和恢复的。
其他东西应该提升
半群
,并具有该
幺半群
实例。当然,我指的是
幺半群
实例。如果我混淆了任何人,请原谅。
fold
(asum .) . sequenceA