鉴于两个列表[a, b]
和[c, d]
,我希望得到以下结果:
[(a,c), (a,d), (b,c), (b,d)]
我如何在Haskell中执行此操作?是否有内置功能,或者我应该自己实现?
答案 0 :(得分:25)
[ (x,y) | x<-[a,b], y<-[c,d] ]
这并不需要任何进一步的解释,是吗?
答案 1 :(得分:15)
一直以来的应用风格!
λ> :m + Control.Applicative
λ> (,) <$> ['a','b'] <*> ['c','d']
[('a','c'),('a','d'),('b','c'),('b','d')]
(我已经避开上面的任何String
句法糖,以便与你的榜样保持接近。)
有关信息,(,)
是一个函数的特殊语法,它接受两个参数并从中生成一对:
λ> :t (,)
(,) :: a -> b -> (a, b)
修改:正如leftaroundabout中的his comment所述,您也可以使用liftA2
:
λ> :m + Control.Applicative
λ> let combine = liftA2 (,)
λ> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]
答案 2 :(得分:9)
如何在命令式伪代码中执行此操作?
for each element x in [a,b]:
for each element y in [c,d]:
produce (x,y)
在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
(左下方的评论)这当然非常接近于如何定义this monadic组合子,所以实际上
outerProduct = liftM2 (,)
与liftA2 (,)
相同,并根据列表推导,concatMap
函数,>>=
,<$>
和<*>
进行各种重写运营商。
从概念上讲,这是Applicative
的内容 - 更好地命名为Pairing
, - 因为这两个&#34;容器&#34;的元素配对/&#34;运营商&#34; /无论什么正是Applicative Functor的意思。恰好Haskell的do
符号适用于monad,而不是( yet )liftM2
。
在某种意义上编译时嵌套循环是 Applicative / Pairing仿函数; Monads添加了动态创建嵌套循环的功能,具体取决于&#34;外部&#34;列举。
答案 3 :(得分:8)
最直观的是使用列表理解,其他aproaches包括使用applicative functor:
(,) <$> [1,2,3] <*> [4,5,6]
这是做什么的?
请记住(,) :: a -> b -> (a, b)
使用两个参数并返回一个元组。
<$>
是实际的fmap,(<$>) :: Functor f => (a -> b) -> f a -> f b
它需要一个功能并提升它。在这种情况下,它需要(,)
并将其提升到列表中。因此let x = (,) <$> [1,2]
将生成x :: [b -> (Integer, b)]
,它是采用b
的函数列表,并返回带有一个固定参数(整数,b)的元组。最后,我们使用<*>
应用它来生成所有组合。
答案 4 :(得分:5)
使用列表理解:
s = [a,b]
s' = [c,d]
all_combinations = [(x,y) | x <- s, y <- s']