我在Haskell中定义Zip有什么问题?

unj*_*nj2 1 zip haskell combinators

--  eg. myzip [’a’, ’b’, ’c’] [1, 2, 3, 4] -> [(’a’, 1), (’b’, 2), (’c’, 3)]
myzip :: Ord a => [a] -> [a] -> [(a,a)]
myzip list1 list2 = [(x,y) |  [x, _] <-list1, [y,_] <-list2 ] 
Run Code Online (Sandbox Code Playgroud)

我收到此错误消息:

 Occurs check: cannot construct the infinite type: a = [a]
    When generalising the type(s) for `myzip'
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

Die*_*Epp 10

有三个问题:一个是模式匹配,一个是类型签名,一个是列表理解的性质.这是一个更正版本:

{-# LANGUAGE ParallelListComp #-}
myzip :: [a] -> [b] -> [(a, b)]
myzip xs ys = [(x, y) | x <- xs | y <- ys]
Run Code Online (Sandbox Code Playgroud)
  • 原始类型签名[a] -> [a] -> [(a, a)]意味着两个列表必须具有相同类型的元素.这Ord a是多余的,只是意味着不允许某些类型的元素.
  • 该模式[x, _] <- list1意味着每个元素list1必须是一个双元素列表.请x <- list1改用.
  • 两个列表推导是串联而不是并行.可以将逗号视为"从list1中获取项目,然后从list2中获取"(系列).可以认为两个管道是平行的.

串联和并联之间的区别:

> [[x, y] | x <- "abc", y <- "123"] -- series
["a1","a2","a3","b1","b2","b3","c1","c2","c3"]
> [[x, y] | x <- "abc" | y <- "123"] -- parallel
["a1","b2","c3"]
Run Code Online (Sandbox Code Playgroud)

  • 应该指出的是,并行列表推导不是标准的haskell(这就是为什么它们必须作为ghc扩展启用). (3认同)

Mtn*_*ark 6

如果你zip为了深入了解Haskell而重写,我建议你尝试不使用列表推导来编写它.列表推导是强大的,但有点像Haskell中某些特定情况的方便简写.而且,如您所见,在其他情况下使用它们可能需要非标准扩展(例如ParallelListComp).

想想zip在一般情况下需要做什么,以及如果不满足一般情况会发生什么(可能以两种方式发生!).函数的方程式应该自然地落在其中.