我想將兩個串列與 operator 結合起來 。[1,2,3] [4,5,6] = [1,2,3,4,5,6]
所以我試過這個:
combine2 :: [a] -> [a] -> [a]
combine2 xs ys = [x : ys | x <- xs]
但這給了我:
a.hs:10:19: error:
? Occurs check: cannot construct the infinite type: a ~ [a]
? In the expression: x : ys
In the expression: [x : ys | x <- xs]
In an equation for ‘combine2’: combine2 xs ys = [x : ys | x <- xs]
? Relevant bindings include
x :: a (bound at a.hs:10:28)
ys :: [a] (bound at a.hs:10:13)
xs :: [a] (bound at a.hs:10:10)
combine2 :: [a] -> [a] -> [a] (bound at a.hs:10:1)
|
10 | combine2 xs ys = [x : ys | x <- xs]
如何解決?
uj5u.com熱心網友回復:
修復它的方法是使它更通用。而不是combine2,撰寫combineN和使用它來解決combine2問題。
combine2 :: [b] -> [b] -> [b]
combine2 xs ys = combineN [xs,ys]
combineN :: [[b]] -> [b]
combineN ls = [a | l <- ls, a <- l]
我們只是從串列的引數串列中繪制每個串列,然后從每個串列中繪制和生成每個元素,就像在兩個嵌套回圈的內部回圈中一樣。在偽代碼中:
for l in ls:
for a in l:
produce a
測驗:
> combine2 [1..3] [11..15]
[1,2,3,11,12,13,14,15]
-- l1: l2:
-- [ [1,2,3], [11,12,13,14,15] ] -- outer "loop"
-- [ 1,2,3 , 11,12,13,14,15 ] -- inner "loop"
或者我們可以將其視為將我們的串列放在另一個串列中,形成一種參差不齊的“矩陣”,然后逐行、逐個元素地讀取它:
-- [ [1,2,3] , -l1- [ 1,2,3 ,
-- [11,12,13,14,15] -l2- 11,12,13,14,15
-- ] ]
“行”是lin的連續值,ls = [xs,ys]每行中的元素a是 each中元素的連續值l。
嵌套回圈本質上就是串列推導式。
uj5u.com熱心網友回復:
查看代碼的推斷型別:
> combine2 xs ys = [x : ys | x <- xs]
> :type combine2
combine2 :: [a] -> [a] -> [[a]]
因此,a當您打算回傳“list of a”時,您將回傳“list of ”。編譯器看到這兩個都是串列,并嘗試匹配元素型別,但發現一個包含“list of a”而另一個只是“ a”。由于型別變數a的型別“串列中出現a”,如果他們都是平等的,這將是一種無限回圈的:a= [a]= [[a]]= [[[a]]]= ......,這是幾乎從來沒有你的意思做的,所以不允許typechecker它。
您的代碼執行以下操作:
combine2 [1, 2, 3] [4, 5, 6]
=
[ 1 : [4, 5, 6]
, 2 : [4, 5, 6]
, 3 : [4, 5, 6]
]
=
[ [1, 4, 5, 6]
, [2, 4, 5, 6]
, [3, 4, 5, 6]
]
當您希望它執行此操作時:
combine2 [1, 2, 3] [4, 5, 6]
=
[1, 2, 3, 4, 5, 6]
使用串列推導式的解決方案是迭代每個 list,然后迭代這些串列中的每個專案:
combine2' xs ys = [z | zs <- [xs, ys], z <- zs]
在combine2' [1, 2, 3] [4, 5, 6], firstzs設定為[1, 2, 3], 所以z設定為1, then 2, then 3; thenzs設定為[4, 5, 6],因此z設定為4,然后5,然后6。
您也可以等式地考慮這一點,根據使用以下方法對串列推導式進行脫糖concatMap:
[z | zs <- [xs, ys], z <- zs]
=
concatMap (\ zs -> concatMap (\ z -> [z]) zs) [xs, ys]
=
concatMap (\ zs -> concatMap pure zs) [xs, ys]
=
concatMap (\ zs -> concat (map pure zs)) [xs, ys]
=
concatMap (\ zs -> zs) [xs, ys]
=
concatMap id [xs, ys]
=
concat (map id [xs, ys])
=
concat [xs, ys]
=
foldr ( ) [] [xs, ys]
=
xs ys []
=
xs ys
本質上,您正在連接所有輸入串列,在這種情況下,“all”恰好只有 2 個。
uj5u.com熱心網友回復:
您在這里生成一個串列串列,您ys每次都在其中添加一個值x。因此,這意味著如果xsisxs = [1,3,0,2]和ysis [1,4,2,5],您使用 構造了一個串列串列[[1, 1, 4, 2, 5], [3, 1, 4, 2, 5], [0, 1, 4, 2, 5], [2, 1, 4, 2, 5]]。
你可以在這里使用遞回。這里的基本情況是第一個串列已用盡。在這種情況下,我們回傳第二個串列,因此:
combine2 [] ys = ys
遞回情況是第一個串列不為空并且具有x第一個元素和xs一個(可能是空的)尾部。在這種情況下,我們x在尾部yield和 recurse xs:
combine2 (x:xs) ys = x : combine xs ys
如果我們把這些放在一起,我們得到:
combine2 :: [a] -> [a] -> [a]
combine2 [] ys = ys
combine2 (x:xs) ys = x : combine2 xs ys
我們在這里每次都通過ys遞回的情況。我們可以使用輔助函式,而不是這樣做:
combine2 :: [a] -> [a] -> [a]
combine2 zs ys = go zs
where go [] = ys
go (x:xs) = x : go xs
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/316855.html
