2013-06-03 56 views
7

我想做一個Haskell連接列表。我有[1,2,3]和[4,5,6] ,我想製作[14,15,16,24,25,26,34,35,36]。 我知道我可以使用zipWith或某事,而是怎麼做相當於:在second_array嵌套循環等效

我想我一定要使用地圖和半咖喱功能 的foreach在first_array 的foreach,但真的不能孤軍奮戰:小號

回答

17

你可以使用列表理解來做到這一點:

[x * 10 + y | x <- [1..3], y <- [4..6]] 

事實上,這是一個嵌套循環的直接翻譯,因爲第一個是外於/慢指數,而第二個是更快/內部索引。

12

您可以利用以下事實:名單單子,並使用做記號

do 
    a <- [1, 2, 3] 
    b <- [4, 5, 6] 
    return $ a * 10 + b 

您也可以利用以下事實:名單是合用的仿函數(假設你有Control.Applicative進口):

(+) <$> (*10) <$> [1,2,3] <*> [4,5,6] 

無論結果如下:

[14,15,16,24,25,26,34,35,36] 
5

如果你很喜歡在代碼中看到for你也可以做這樣的事情:

for :: [a] -> (a -> b) -> [b] 
for = flip map 

nested :: [Integer] 
nested = concat nested_list 
    where nested_list = 
      for [1, 2, 3] (\i -> 
      for [4, 5, 6] (\j -> 
       i * 10 + j 
      ) 
     ) 

你也可以看看forIdentity一個更慣用的做法。

1

嵌套循環對應於map或類似函數的嵌套使用。第一個近似值:

notThereYet :: [[Integer]] 
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3] 

這給出了嵌套列表,您可以用兩種方法消除嵌套列表。一種是使用concat :: [[a]] -> [a]功能:

solution1 :: [Integer] 
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]) 

另一種是使用這個內置的功能:

concatMap :: (a -> [b]) -> [a] -> [b] 
concatMap f xs = concat (map f xs) 

使用:

solution2 :: [Integer] 
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3] 

其他人都提到列表推導和列表單子,但那些真正的底層嵌套使用concatMap

0

整數兩個列表的級聯的一般解決方案是這樣的:

concatInt [] xs = xs 
concatInt xs [] = xs 
concatInt xs ys = [join x y | x <- xs , y <- ys ] 
    where 
    join x y = firstPart + secondPart 
     where 
     firstPart = x * 10^lengthSecondPart 
     lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y)) 
     secondPart = y 

實施例:concatInt [1,2,3] [4,5,6] == [14,15,16 ,24,25,26,34,35,36]

更復雜的例子: concatInt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44, 3,224,22,2999,244,23,1024,102,10999,1044,103,124,12,1999,144,13,10024,1002,100999,10044,1003,20024,2002,200999,20044,2003]

1

因爲已經有10個符號和列表理解。我知道的唯一的其他選項是通過Control.MonadliftM2組合器。這與前兩個完全相同。

liftM2 (\a b -> a * 10 + b) [1..3] [4..6] 
+0

...只有更短(除了所有的第一個)。 :) nicccce! –