这个矩阵转置函数是有效的,但是我试图理解它的一步一步的执行,我不明白。
transpose:: [[a]]->[[a]]
transpose ([]:_) = []
transpose x = (map head x) : transpose (map tail x)
与
transpose [[1,2,3],[4,5,6],[7,8,9]]
它将返回:
[[1,4,7],[2,5,8],[3,6,9]]
我不明白连接运算符是如何处理map的。它是在同一个函数调用中连接x的每个头?怎么做?
这是不是
(map head x)
创建每个列表的head元素的列表?
7条答案
按热度按时间5kgi1eie1#
让我们看看函数对示例输入做了什么:
请注意,我选择的简化项的顺序与haskell将使用的求值顺序不同,但这不会改变结果。
编辑:针对您编辑的问题:
这是不是
创建每个列表的head元素的列表?
是的,是的。
ssgvzors2#
cons运算符
:
将类型为a
的对象附加到类型为[a]
的列表。在LHS是一个列表(
a = [b]
),而RHS是列表的列表([a] = [[b]]
),因此这样的构造是有效的。在您的示例中,
map head x
和map tail x
拆分矩阵进入
(and是的,
map head x
是每个列表的头元素的列表。)第二部分被转置(有关详细步骤,请参见@sepp2k的答案)以形成因此将
[1,4,7]
与此相结合得到yqkkidmi3#
ghci
是您的朋友:即使你不理解
map
(这个问题你应该尽快解决!),这些表达式的类型也能告诉你它们是如何工作的。第一个表达式是从列表列表中提取的一个列表,所以让我们给它一个简单的向量,看看会发生什么。你可能想写
但无法进行类型检查:
请记住,参数的类型是列表的列表,因此
变得有点复杂
执行相同的操作,但使用
tail
而不是head
,得到正如您所看到的,
transpose
的定义是重复地用map head x
切掉第一个“行”,并转置其余的行,即map tail x
。von4xj4u4#
这些事情都是一样的:
它是lambda-expression,这意味着i返回每个xs的xs头。例如:
这很简单
xxb16uws5#
顺便说一下,当给定一个像
[[1,2,3], [], [1,2]]
这样的输入时,这个函数不起作用。但是,来自Data.List
的转置函数将接受这个输入,并返回[[1,1], [2,2], [3]]
。当我们调用递归的
transpose
代码时,我们需要去掉[]
。lo8azlld6#
如果要使用
head
和tail
转置 * 矩形 * 数组,请事先确保列数相同,然后可以执行以下操作:显然,它也适用于方阵和单例,但当标准实现提供更多选项时,我看不出它有多大用处。
ovfsdjhp7#
或者,您也可以定义自己的函数。我发现了一种在Haskell中仅使用列表解析实现矩阵转置的更简单方法。它适用于具有非空元素的通用
m* n
矩阵