在Haskell中扩展左活页夹

在Haskell中扩展左活页夹,haskell,Haskell,我试图理解哈斯克尔的单子,所以我在阅读 让我们从上面的站点考虑一段代码: maternalGrandfather :: Sheep -> Maybe Sheep maternalGrandfather s = (return s) >>= mother >>= father fathersMaternalGrandmother :: Sheep -> Maybe Sheep fathersMaternalGrandmother s = (return s)

我试图理解哈斯克尔的单子,所以我在阅读

让我们从上面的站点考虑一段代码:

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 for
expand 10 s
makes
(返回s)>>=父>>=父>>=父>>=父>>=父>>=父。。(10次)


如何实施。可能使用递归进行扩展,但我无法想象停止时会返回什么。

您可以使用iterate进行此操作

iterate (>>= father) (return s) !! 10

将10更改为所需的父应用程序的数量。

如果您有一个关于一元操作的列表(例如,
[IO x]
[Maybe Int]
或其他什么),您可以使用
sequence
函数将所有这些操作链接在一起。(请注意,它们首先必须具有相同的类型才能将它们放入列表中。)

如果您有一个输入列表,并且希望将它们传递给一元函数(例如,
String->Maybe Int
),您可以
将您的函数映射到该列表上,从而生成一元操作列表。然后,您可以使用
序列
链接这些。但这是一种常见的模式,因此有一个函数用于此:您可以直接使用
mapM
来处理这种情况


一般来说,在Control.Monad中查看一下其他与Monad相关的有用函数。

与其考虑如何对一元值重复应用“一元函数”,不如考虑如何“折叠”将一元函数列表转换为一个函数,以后可以应用于一元值

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

foldr
接收函数、初始值和列表作为参数。它所做的是用函数替换列表中的每个构造函数
,并用初始值替换列表末尾的空构造函数
[]
。例如,考虑下面的Its列表:

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
我们越来越近了。我们需要像
(.)
这样的复合运算符,但对于一元函数,它可以组合两个一元函数并生成另一个。某种类型的东西
Monad m=>(a->ma)->(a->ma)->a->ma
,我们发现更一般(但仍然合适)的运算符:


现在,您可以使用
(>>=)

将结果应用于原始一元值,一个无限序列的一元操作将永远不会返回。
(>>=)
运算符太严格了。@MathematicalArchid这通常不是真的,
>=
的操作语义完全取决于如何为任何特定的monad定义函数。e、 g
fix(\x->x:[[1]]>>=scanl(+)1)
定义得非常好。好的,它不是通用的。我有一个列表,我的停止约束是[]@Gilgamesz,你可以使用
find
添加停止约束。
 (\x -> x + 1) . (\y -> y + 2) . id
 (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
  combineMonadicFunctions :: Monad m => [a -> m a] -> a -> m a
  combineMonadicFunctions fs = foldr (<=<) return fs