haskell - 如何使用 zip 和列表理解来定义 zipWith

标签 haskell zip list-comprehension zipwith

我正在尝试使用 zip 和列表理解来编写 zipWith 函数。应用该函数后,我需要压缩两个列表。但是我不知道在哪里使用列表理解。

我尝试对每个列表进行两个列表理解。

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = zip [f x | x <- xs] [f y | y <- ys]

我希望该功能与 zipWith 相同,但它没有加载并给出错误:

Occurs check: cannot construct the infinite type:
        c ~ (b -> c, b -> c)
      Expected type: [c]
        Actual type: [(b -> c, b -> c)]
    • In the expression: zip [f x | x <- xs] [f y | y <- ys]
      In an equation for ‘zipWith'’:
          zipWith' f xs ys = zip [f x | x <- xs] [f y | y <- ys]

    • Relevant bindings include
        ys :: [b] (bound at tutorial5.hs:166:15)
        f :: a -> b -> c (bound at tutorial5.hs:166:10)
        zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
          (bound at tutorial5.hs:166:1)
    |
166 | zipWith' f xs ys = zip [f x | x <- xs] [f y | y <- ys]

最佳答案

嗯,这里有一些问题。在顶层,考虑 zip :: [a] -> [b] -> [(a,b)] 的签名:它不可能返回 [c]哪里c不是元组,所以你不需要 zip成为新 zipWith 中的外部函数调用。您的类型错误是由于 GHC 注意到它需要强制 c 引起的。是一个元素类型包含 c 的元组它们本身(因为 f 应用于任何东西将始终具有类型 b -> c )。

您的列表推导式也基本上与 map f xs 相同。和map f ys 。其中第二个无法进行类型检查,因为 ys 的每个元素是 b ,并且您无法申请fb (它的第一个参数是 a )。

您可以首先压缩输入列表以获取 [(a,b)] ,然后使用列表理解来运行 f每对:

zipWith' f xs ys = [f x y | (x,y) <- zip xs ys]

或者,与 mapuncurry而不是列表理解:

zipWith' f xs ys = map (uncurry f) $ zip xs ys

或者,使用 GHC 并行列表理解扩展 ( -XParallelListComp ),明确设计为模仿 zip :

zipWith' f xs ys = [f x y | x <- xs | y <- ys]

如上所述,你不能真正做到 zip 最后,因为它会生成元组。你可以做类似的事情

zipWith' f xs ys = [fx y | (fx, y) <- zip [f x | x <- xs] ys]

适用 f到第一个列表的元素(在 [f x | x <- xs]map f xs 中),用第二个参数列表压缩此部分应用函数列表,然后将部分函数应用于外部理解中相应的第二个参数,但这有点迂回。

关于haskell - 如何使用 zip 和列表理解来定义 zipWith,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58422267/

相关文章:

haskell - cabal 何时重新编译包含 Template Haskell 的模块?

python - 按第二个元素拆分元组列表 - python

c# - 加密的 zip 文件也可以保护其内部目录吗

javascript - 如何使用 Node Js、Archiver 和 Express 正确下载 .zip 文件

ios - zbar #ifdef 问题与 iOS 中的 minizip

python - 将列表理解表达式拆分为多行以更好地了解发生了什么?

coffeescript - 是否可以通过 CoffeeScript 理解从回调中收集结果?

haskell - 为 n 维网格类型编写 cojoin 或 cobind

Haskell IO 代码不进行类型检查

haskell - 'Monad (Writer String)' 的非法实例声明