这是一个类型错误。
当你写“x from xs get-index c”(即x <- xs !! c)时,你“来自”xs !! c 的东西不一定是一个列表。这是一个技术细节,但它很重要。 “从”箭头来自 monad syntax/do-notation。列表推导式实际上只是一个专门用于 List monad 的 do 表达式;所以箭头 <- 的右侧需要是 List monad 中的一个列表。
首先,您可以通过使用单例列表“作弊”来解决此问题,例如:
ziplike xs ys = [ (x,y) | c <- [0 .. min (length xs) (length ys) - 1],
x <- [xs !! c],
y <- [ys !! c]]
所以这些左箭头不是“让”变量绑定,但它们产生笛卡尔积:但 n 事物与 1 事物与 1 事物的笛卡尔积只是 n * 1 * 1 == n 事物。所以这很棒,虽然有点奇怪并且可能效率低下。
要做你想做的事情(在列表理解中绑定 x 和 y),你还可以编写如下内容:
ziplike xs ys = [let x = xs !! c; y = ys !! c in (x, y)
| c <- [0 .. min (length xs) (length ys) - 1]]
-- or --
ziplike xs ys = [(x, y)
| c <- [0 .. min (length xs) (length ys) - 1],
let x = xs !! c, let y = ys !! c]
-- or --
ziplike xs ys = [(x, y)
| c <- [0 .. min (length xs) (length ys) - 1],
let x = xs !! c; y = ys !! c]
请注意,这些都是用逗号附加的 do-notation 想法。当然,所有这些看起来都比
ziplike xs ys = [(xs !! c, ys !! c) | c <- [0..min (length xs) (length ys) - 1]
做同样的事情。
话虽如此,所有这些东西比zip 函数的递归字符效率低得多:如果我将列表大小加倍,您的实现需要 4 倍的时间来处理整个清单; zip 只需要两倍的时间。所以在你的编程中要注意这个“隐藏的 O(n2) 因素”。