8

我想在 Haskell 中做一个串联列表。我有 [1,2,3] 和 [4,5,6],我想生产 [14,15,16,24,25,26,34,35,36]。我知道我可以使用 zipWith 或 sth,但如何做相当于: foreach in first_array foreach in second_array

我想我必须使用 map 和 half curried 函数,但不能真正单独使用:S

4

6 回答 6

20

您可以使用列表推导来做到这一点:

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

实际上这是嵌套循环的直接翻译,因为第一个是外部/较慢的索引,第二个是较快/内部的索引。

于 2013-06-03T19:35:52.877 回答
15

您可以利用列表是 monad 的事实并使用do 表示法

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]
于 2013-06-03T19:37:21.337 回答
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寻找更惯用的方法。

于 2013-06-03T20:33:19.283 回答
2

嵌套循环对应于嵌套使用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.

于 2013-06-03T21:09:36.357 回答
1

因为do符号和列表理解已经说过了。我知道的唯一其他选择是通过liftM2来自Control.Monad. 这与前两个完全相同。

liftM2 (\a b -> a * 10 + b) [1..3] [4..6]
于 2013-06-04T20:01:20.890 回答
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]

于 2013-06-04T05:27:42.850 回答