Haskell中两个列表的元素的所有组合

Ben*_*Ben 17 combinations haskell tuples list

给出两个列表,[a, b]并且[c, d],我想得到以下结果:

[(a,c), (a,d), (b,c), (b,d)]
Run Code Online (Sandbox Code Playgroud)

我怎么能在Haskell中做到这一点?是否有内置功能,或者我应该自己实现?

lef*_*out 27

[ (x,y) | x<-[a,b], y<-[c,d] ]
Run Code Online (Sandbox Code Playgroud)

这不需要任何进一步的解释,是吗?

  • @Ben:`combos = liftA2(,)`,这基本上等同于Jubobs的建议. (11认同)

jub*_*0bs 15

应用风格一路走来!

?> :m + Control.Applicative
?> (,) <$> ['a','b'] <*> ['c','d']
[('a','c'),('a','d'),('b','c'),('b','d')]
Run Code Online (Sandbox Code Playgroud)

(我已经避开了String上面的任何语法糖,以便与你的榜样保持接近.)

有关信息,(,)是一个函数的特殊语法,它接受两个参数并从中生成一对:

?> :t (,)
(,) :: a -> b -> (a, b)
Run Code Online (Sandbox Code Playgroud)

编辑:正如指出的leftaroundabout他的评论,你也可以使用liftA2:

?> :m + Control.Applicative
?> let combine = liftA2 (,)
?> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]
Run Code Online (Sandbox Code Playgroud)


Wil*_*ess 9

你怎么能在命令式伪代码中做到这一点?

for each element x in [a,b]:
    for each element y in [c,d]:
        produce (x,y)
Run Code Online (Sandbox Code Playgroud)

在Haskell中,这是写成的

outerProduct xs ys =
   do
       x <- xs          -- for each x drawn from xs:
       y <- ys          --   for each y drawn from ys:
       return (x,y)     --      produce the (x,y) pair
Run Code Online (Sandbox Code Playgroud)

(左下方的评论)这当然非常接近monadicliftM2组合子的定义,所以事实上

outerProduct = liftM2 (,)
Run Code Online (Sandbox Code Playgroud)

这是一样的liftA2 (,),并在列表内涵,而言其各种重新写入concatMap功能>>=,<$><*>运营商.

从概念上讲,虽然这是Applicative最好的名称Pairing- 因为这两个"容器"/"载体"的元素配对/无论什么正是Applicative Functor的意思.恰好Haskell的do符号适用于monad,而不是()适用于应用程序.

在某种意义上,编译时嵌套循环 Applicative/Pairing仿函数; Monads添加了动态创建嵌套循环的功能,具体取决于"外部"枚举产生的值.

  • 值得注意的是,`do`-notation和list comprehensions实际上都是同一个monadic组合器的语法糖,即`[a,b] >> =\x - > [c,d] >> =\y - > return(x,y)`. (4认同)

con*_*t3d 8

最直观的是使用列表理解,其他aproaches包括使用applicative functors:

(,) <$> [1,2,3] <*> [4,5,6]
Run Code Online (Sandbox Code Playgroud)

那这是做什么的呢?

请记住,使用(,) :: a -> b -> (a, b)两个参数并返回一个元组.

<$>实际上是fmap,(<$>) :: Functor f => (a -> b) -> f a -> f b 它需要一个功能并解除它.在这种情况下,它需要(,)并将其提升到列表上.因此let x = (,) <$> [1,2]会生成x :: [b -> (Integer, b)]哪个是函数列表,b并使用一个固定参数返回元组(整数,b).最后,我们使用它<*>来生成所有组合.


Ste*_*and 6

使用列表理解:

s = [a,b]
s' = [c,d]

all_combinations = [(x,y) | x <- s, y <- s']
Run Code Online (Sandbox Code Playgroud)