在Haskell中扩展左侧绑定器

时间:2016-04-07 15:16:18

标签: haskell

我正在尝试理解Haskell中的monad,所以我正在阅读https://wiki.haskell.org/All_About_Monads

让我们考虑一下上面的一段代码:

maternalGrandfather :: Sheep -> Maybe Sheep
maternalGrandfather s = (return s) >>= mother >>= father

fathersMaternalGrandmother :: Sheep -> Maybe Sheep
fathersMaternalGrandmother s = (return s) >>= father >>= mother >>= mother

一切都很清楚。但我想知道如何制作一个长的(也许是无限的)序列。我的意思是例如:

expand :: Int -> Sheep -> MaybeSheep

例如展开expand 10 s使(return s) >>= father >>= father >>= father >>= father >>= father .. ( 10 times)

如何实施它。也许使用递归扩展,但我无法想象停止时可以返回什么。

3 个答案:

答案 0 :(得分:4)

不要考虑如何将“monadic函数”重复应用于monadic值,而是考虑如何将monadic函数列表“折叠”为单个函数,以后可以将其应用于monadic值。 / p>

在Haskell中,“折叠”列表的原型组合称为foldr

foldr :: (a -> b -> b) -> b -> [a] -> b

foldr收到函数初始值列表作为参数。它的作用是使用函数替换列表的每个构造函数:,并使用初始值替换列表末尾的空构造函数[]。例如,请考虑以下的整数列表:

4 : 5 : 77 : 34 : []

假设我们要将列表的所有元素添加到88.我们可以这样做

foldr (+) 88 (4 : 5 : 77 : 34 : [])

这实际上等于

4 + 5 + 77 + 34 + 88.

好的,现在想象一下列表中的元素是a -> a类型的函数。我们可以将两个函数与组合运算符(.)结合起来,但是,我们用什么函数替换列表末尾[]?我们不想添加任何进一步的修改,因此我们将“中性元素”用于组合,身份函数id

 foldr (.) id ((\x -> x + 1) : (\y -> y + 2) : []) 

这等于

 (\x -> x + 1) . (\y -> y + 2) . id

我们越来越近了。我们需要像(.)这样的合成运算符,但对于monadic函数,它可以组合两个monadic函数并生成另一个函数。某种类型Monad m => (a -> m a) -> (a -> m a) -> a -> m aLooking for the signature in Hoogle,我们发现稍微更通用(但仍然合适)的运算符(<=<)

 (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c

只留下一个细节:monadic功能组合的“身份”是什么?嗯,它是return,它将纯粹的价值置于“中性”的一元背景中。对于Maybereturn只是Just构造函数。

所以,总之:如果你想组合一个monadic函数列表,你可以这样做:

  combineMonadicFunctions :: Monad m => [a -> m a] -> a -> m a
  combineMonadicFunctions fs = foldr (<=<) return fs

现在,您可以使用(>>=)将结果应用于原始monadic值。

答案 1 :(得分:3)

您可以使用iterate

执行此操作
iterate (>>= father) (return s) !! 10

将10更改为父亲所需的申请数量。

答案 2 :(得分:2)

如果您有关于monadic操作的列表(例如,[IO x][Maybe Int]或某些内容),则可以使用sequence函数将所有这些操作链接在一起。 (请注意,它们必须具有相同的类型才能将它们放在列表中。)

如果你有一个输入列表,并且想要将它们传递给一个monadic函数(例如,String -> Maybe Int),你可以在列表中map你的函数,从而得到一个monadic动作列表。然后,您可以使用sequence来链接这些链接。但这是一种常见的模式,因此有一个功能:您可以直接使用mapM

一般情况下,请在Control.Monad中查看其他有用的与monad相关的功能。