首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >N-列表上的Control.Applicative提升

N-列表上的Control.Applicative提升
EN

Stack Overflow用户
提问于 2016-09-11 14:47:20
回答 3查看 81关注 0票数 0

我对Haskell非常陌生,我想知道如何在不使用固定的理解列表(或者像liftA这样的应用函子)的情况下实现以下输出。

代码语言:javascript
复制
> [ [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。

代码语言:javascript
复制
 λ> :m + Control.Applicative
 λ> let combine = liftA2 (,)
 λ> combine "ab" "cd"
 [('a','c'),('a','d'),('b','c'),('b','d')]

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-11 15:18:11

如果使用相同列表[1,11]的n个副本,则可以使用replicateM

代码语言:javascript
复制
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来执行多列表笛卡儿产品:

代码语言:javascript
复制
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]]
票数 3
EN

Stack Overflow用户

发布于 2016-09-11 15:24:28

如果您想要灵活地处理不仅仅是[1,11]列表的输入

代码语言:javascript
复制
λ> import Control.Applicative (liftA2)
λ> let sumsOfCombinations xs = (:[]) . sum <$> foldr (liftA2 (:)) [[]] xs

您可以将任何数字列表传递给它:

代码语言:javascript
复制
λ>  sumsOfCombinations' [[0,100],[-1,0,1],[0,1000]]
[-1,999,0,1000,1,1001,99,1099,100,1100,101,1101]

包括但不限于你的例子:

代码语言:javascript
复制
λ> 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]]

它的类型如下:

代码语言:javascript
复制
λ> :t sumsOfCombinations
sumsOfCombinations :: (Num b, Foldable t) => t [b] -> [[b]]

正如所写的,sumsOfCombinations给出了您想要的确切输出。但是,我认为没有必要返回列表,所以我会选择:

代码语言:javascript
复制
λ> 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]

请注意,您可以从每个列表中提取一个助手,以便从列表中为您提供元素的组合:

代码语言:javascript
复制
λ> 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]]

所以你有:

代码语言:javascript
复制
sumsOfCombinations xs = (:[]) . sum <$> combinations xs

或者,如果您不需要返回列表列表:

代码语言:javascript
复制
sumsOfCombinations' xs = sum <$> combinations xs
票数 0
EN

Stack Overflow用户

发布于 2016-09-11 15:35:44

更普遍地说,您想要的是给定列表中所有列表的笛卡尔积。一旦你有了它,你就可以用你喜欢的任何方式组合它们。

代码语言:javascript
复制
cartesian :: [[a]] -> [[a]]
cartesian [] = [[]]
cartesian (xs:xss) = [x : ys | x <- xs, ys <- cartesian xss]

mkSums :: [[Int]] -> [[Int]]
mkSums = map ((\x -> [x]) . sum) . cartesian
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39437279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档