Haskell 使用mplus创建函数列表
如何使用。我希望具有类似的效果,但将函数列表作为参数:Haskell 使用mplus创建函数列表,haskell,Haskell,如何使用。我希望具有类似的效果,但将函数列表作为参数: tryFuncs :: [a -> Maybe b] -> a -> Maybe b ... 那么一个像这样的电话 tryFuncs [f, g, h] x 将成为可能,并按照 (f x) `mplus` (g x) `mplus` (h x) 如何实现这一点?最简单的方法是将msum(mplus的列表版本)与map一起使用: tryFuncs fs x = msum $ map ($ x) fs (最终,这个解决
tryFuncs :: [a -> Maybe b] -> a -> Maybe b
...
那么一个像这样的电话
tryFuncs [f, g, h] x
将成为可能,并按照
(f x) `mplus` (g x) `mplus` (h x)
如何实现这一点?最简单的方法是将
msum
(mplus的列表版本)与map
一起使用:
tryFuncs fs x = msum $ map ($ x) fs
(最终,这个解决方案将与厄尔詹·约翰森的答案相同,因为可能sMonadPlus
相当于第一个
的行为。但这是a->b
Monoid的一个简洁的小应用,很容易被忽略。)
从概念上讲,您正在寻找的函数是<代码>mconcat
tryFuncs' :: Monoid b => [a -> Maybe b] -> a -> Maybe b
tryFuncs' = mconcat
不幸的是,Maybe
的默认Monoid
实例并不是您想要的(“忽略无任何内容”
,mappend
仅是内容”),否则该解决方案会非常简洁
但是有一个First
包装器围绕着Maybe
提供了“retainfirstJust
”行为,因此
-- newtype First a = First (Maybe a)
tryFuncsFirst :: [a -> First b] -> a -> First b
tryFuncsFirst = mconcat
剩下的是先将包裹/展开到中
firstify :: (a -> Maybe b) -> (a -> First b)
firstify f = First . f
firstifyList :: [a -> Maybe b] -> [a -> First b]
firstifyList = map firstify
getFirst :: First a -> Maybe a -- Defined in Data.Monoid
现在您可以通过包装mconcat UNWRAPING来恢复所需的功能
[a -> Maybe b] -> a -> Maybe b
tryFuncs fs x = getFirst (mconcat (firstifyList xs) x)
但是这是如何工作的呢?这里有两个幺半群在起作用,第一个a
和幺半群b=>(a->b)
,而后一个就是魔法发生的地方。要稍微解释一下实例,请使用
formappend
(a <> b) x = a x <> b c
-- and therefore
mconcat [a,b,c] x = mconcat [a x, b x, c x] -- (1)
(a b)x=a x b c
--因此
mconcat[a,b,c]x=mconcat[ax,bx,cx]--(1)
因此,现在可以理解上述代码:
First
-包装所有输入函数,将它们从a->Maybe b
带到a->First b
,这是相同的,但具有不同的Maybe
实例
mconcat
函数列表,它使用我刚才提到的monoidb=>(a->b)
实例。创建的列表中的所有函数都应用于x
,留下一个第一个b
的列表,然后再次连接,如(1)所示
再次从第一个
包装中提取得到的可能
值
@larsmansmsum
对空列表使用mzero
,因此这是不必要的。