我对Haskell非常陌生,我想知道如何在不使用固定的理解列表(或者像liftA这样的应用函子)的情况下实现以下输出。
> [ [x+y+z] | x <- [1,11], y <- [1,11], z <- [1,11]]
> [[3],[13],[13],[23],[13],[23],[23],[33]]上面的代码示例仅处理3个列表,例如xyz。如何使用n个列表,例如[1,11]或[1,11,11,11,11,11,11,11,11,11,11,11,11,11]实现同样的目标?
PS -我看过使用控制应用函子liftA,但它仅限于liftA3。
λ> :m + Control.Applicative
λ> let combine = liftA2 (,)
λ> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]谢谢。
发布于 2016-09-11 15:18:11
如果使用相同列表[1,11]的n个副本,则可以使用replicateM。
import Control.Monad
ghci> replicateM 3 [1,11]
[[1,1,1],[1,1,11],[1,11,1],[1,11,11],[11,1,1],[11,1,11],[11,11,1],[11,11,11]]
ghci> map sum (replicateM 3 [1,11])
[3,13,13,23,13,23,23,33]通常,您可以使用sequence来执行多列表笛卡儿产品:
ghci> sequence [ [1,11], [2,22], [3,33] ]
[[1,2,3],[1,2,33],[1,22,3],[1,22,33],[11,2,3],[11,2,33],[11,22,3],[11,22,33]]发布于 2016-09-11 15:24:28
如果您想要灵活地处理不仅仅是[1,11]列表的输入
λ> import Control.Applicative (liftA2)
λ> let sumsOfCombinations xs = (:[]) . sum <$> foldr (liftA2 (:)) [[]] xs您可以将任何数字列表传递给它:
λ> sumsOfCombinations' [[0,100],[-1,0,1],[0,1000]]
[-1,999,0,1000,1,1001,99,1099,100,1100,101,1101]包括但不限于你的例子:
λ> sumsOfCombinations $ replicate 3 [1,11]
[[3],[13],[13],[23],[13],[23],[23],[33]]
λ> sumsOfCombinations $ replicate 4 [1,11]
[[4],[14],[14],[24],[14],[24],[24],[34],[14],[24],[24],[34],[24],[34],[34],[44]]它的类型如下:
λ> :t sumsOfCombinations
sumsOfCombinations :: (Num b, Foldable t) => t [b] -> [[b]]正如所写的,sumsOfCombinations给出了您想要的确切输出。但是,我认为没有必要返回列表,所以我会选择:
λ> let sumsOfCombinations' xs = sum <$> foldr (liftA2 (:)) [[]] xs
λ> :t sumsOfCombinations'
sumsOfCombinations' :: (Num b, Foldable t) => t [b] -> [b]
λ> sumsOfCombinations' $ replicate 3 [1,11]
[3,13,13,23,13,23,23,33]请注意,您可以从每个列表中提取一个助手,以便从列表中为您提供元素的组合:
λ> let combinations = foldr (liftA2 (:)) [[]]
λ> combinations [[1,2],[3,4],[5,6]]
[[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]所以你有:
sumsOfCombinations xs = (:[]) . sum <$> combinations xs或者,如果您不需要返回列表列表:
sumsOfCombinations' xs = sum <$> combinations xs发布于 2016-09-11 15:35:44
更普遍地说,您想要的是给定列表中所有列表的笛卡尔积。一旦你有了它,你就可以用你喜欢的任何方式组合它们。
cartesian :: [[a]] -> [[a]]
cartesian [] = [[]]
cartesian (xs:xss) = [x : ys | x <- xs, ys <- cartesian xss]
mkSums :: [[Int]] -> [[Int]]
mkSums = map ((\x -> [x]) . sum) . cartesianhttps://stackoverflow.com/questions/39437279
复制相似问题