2010-03-30 21 views
1
-- 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 ] 

我收到此錯誤信息:我在Haskell中對Zip的定義有什麼問題?

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

回答

10

有三個問題:一個是模式匹配,一個是類型簽名,一個是列表理解的性質。這裏是一個修正版本:

{-# 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
  • 這兩個列表解析是串聯而不是並行的。把逗號看作「從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"] 
+3

應該指出,並行列表解析不是標準的haskell(這就是爲什麼它們必須作爲ghc擴展來使能)。 – sepp2k 2010-03-30 21:35:19

6

如果你爲了深入瞭解Haskell中,我建議你嘗試寫不使用列表解析重寫zip。列表解析是強大的,但有點像Haskell中某些特定情況的簡便速記。而且,如您所見,在其他情況下使用它們可能需要非標準擴展名(例如ParallelListComp)。

想想在一般情況下zip需要做什麼,以及如果不滿足一般情況(可能發生在兩種方式!)會發生什麼情況。該函數的方程應該自然地落在那個之外。

相關問題