我在 Haskell 中对 Zip 的定义有什么问题?
-
23-09-2019 - |
题
-- 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 ]
我收到此错误消息:
Occurs check: cannot construct the infinite type: a = [a]
When generalising the type(s) for `myzip'
Failed, modules loaded: none.
解决方案
存在三个问题:一是模式匹配,一是类型签名,一是列表理解的性质。这是一个更正的版本:
{-# LANGUAGE ParallelListComp #-}
myzip :: [a] -> [b] -> [(a, b)]
myzip xs ys = [(x, y) | x <- xs | y <- ys]
- 原始类型签名,
[a] -> [a] -> [(a, a)]
, ,意味着两个列表必须具有相同类型的元素。这Ord a
是多余的,只是意味着某些类型的元素是不允许的。 - 图案
[x, _] <- list1
意味着每个元素list1
必须是一个二元素列表。使用x <- list1
反而。 - 这两个列表推导式是串联的而不是并行的。将逗号视为“从列表 1 中获取项目,然后从列表 2 中获取项目”(系列)。将两个管道视为平行。
串联和并联的区别:
> [[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"]
其他提示
如果您为了重写zip
洞悉哈斯克尔,我建议你尝试写不使用列表解析。 List内涵是强大的,但有点像在Haskell某些特定情况下方便的速记。而且,正如你看到的,在其他情况下使用它们可能需要非标准的扩展名(如ParallelListComp
)。
想想zip
需要在一般的情况下做的,要是一般情况下不符合情况(可通过两种方式进行!)。该函数的方程式应该自然脱落的那个。
不隶属于 StackOverflow