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

发布于 2024-08-27 07:09:35 字数 401 浏览 9 评论 0原文

--  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.
--  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 ] 

I get this error message:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十年不长 2024-09-03 07:09:35

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

{-# LANGUAGE ParallelListComp #-}
myzip :: [a] -> [b] -> [(a, b)]
myzip xs ys = [(x, y) | x <- xs | y <- ys]
  • 原始类型签名,[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"]

There are three problems: One is the pattern match, one is the type signature, and one is the nature of the list comprehension. Here is a corrected version:

{-# LANGUAGE ParallelListComp #-}
myzip :: [a] -> [b] -> [(a, b)]
myzip xs ys = [(x, y) | x <- xs | y <- ys]
  • The original type signature, [a] -> [a] -> [(a, a)], meant that both lists had to have the same type of element. The Ord a was superfluous, and just meant that certain types of elements were disallowed.
  • The pattern [x, _] <- list1 means that each element of list1 must be a two-element list. Use x <- list1 instead.
  • The two list comprehensions are in series instead of parallel. Think of the comma as, "Take items from list1, then from list2" (series). Think of the two pipes as being parallel.

The difference between series and parallel:

> [[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"]
自由范儿 2024-09-03 07:09:35

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

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

If you re-writing zip in order to gain insight into Haskell, I'd suggest that you try to write it without using list comprehensions. List comprehensions are powerful, but are somewhat like a convenient shorthand for some particular cases in Haskell. And, as you see, to use them in other cases might require non-standard extensions (such as ParallelListComp).

Think about what zip needs to do in the general case, and what happens if the general case isn't met (which can happen in two ways!). The equations for the function should fall naturally out of that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文