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)
这不需要任何进一步的解释,是吗?
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)
你怎么能在命令式伪代码中做到这一点?
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添加了动态创建嵌套循环的功能,具体取决于"外部"枚举产生的值.
最直观的是使用列表理解,其他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).最后,我们使用它<*>
来生成所有组合.
使用列表理解:
s = [a,b]
s' = [c,d]
all_combinations = [(x,y) | x <- s, y <- s']
Run Code Online (Sandbox Code Playgroud)