简体   繁体   English

如何将部分函数应用于元组列表

[英]How to apply partial functions to list of tuples

The title of this question might sound misleading, but I wasnt sure how else to explain what I'm trying to do. 这个问题的标题听起来可能有误导性,但是我不确定其他如何解释我要做什么。

I'm experimenting with non-deterministic data structures. 我正在尝试不确定的数据结构。 I'm trying to produce all possible combinations of a set of partially apply operators and a list of tuples: 我正在尝试产生一组部分应用运算符和一个元组列表的所有可能组合:

-- test.hs
makeTupleList :: (Int, Int) -> [(Int, Int)] 
makeTupleList (a, b) = ZipList [(+2), (-2)] <*> ZipList [a, b]

I want makeTupleList to return something like: 我希望makeTupleList返回类似以下内容的内容:

[(a + 2, b + 2), (a + 2, b - 2), (a - 2, b + 2), (a - 2, b - 2)]

But I'm clearly doing something wrong because I keep getting this error: 但我显然做错了,因为我不断收到此错误:

Couldn't match type `ZipList' with `[]'

How do I get my desired result? 如何获得理想的结果?

There's a mismatch between the type you declared and the type the function actually has. 您声明的类型与函数实际具有的类型之间不匹配。

Let's just check the body of the function 让我们检查一下函数的主体

*> :t \(a, b) -> ZipList [(+2), (-2)] <*> ZipList [a, b]
\(a, b) -> ZipList [(+2), (-2)] <*> ZipList [a, b]
  :: (Num (b -> b), Num b) => (b, b) -> ZipList b

Eep! That's not good at all. 那根本不好。

So let's fix the error. 因此,让我们修复错误。 The first error is that -2 trips you up, because it parses as negative two, not an operator section. 第一个错误是-2您绊倒,因为它解析为负两个,而不是运算符部分。

You can see that by typechecking just that fragment: 您可以通过只检查该片段来查看:

*> :t (-2)
(-2) :: Num a => a

Ok, so we'll change it to an explicit lambda, and get closer: 好的,因此我们将其更改为一个显式的lambda,然后更进一步:

*> :t \(a, b) -> ZipList [(+2), (\x -> x - 2)] <*> ZipList [a, b]
\(a, b) -> ZipList [(+2), (\x -> x - 2)] <*> ZipList [a, b]
  :: Num b => (b, b) -> ZipList b

Now we see the conceptual error (you can see even more if you test it). 现在我们看到了概念上的错误(如果进行测试,您甚至可以看到更多)。 We're just getting back [a+2,b-2] . 我们刚回来[a+2,b-2] That's what ziplist does -- "zips" the lists together. 这就是ziplist 所做的 -将列表“压缩”在一起。 It doesn't take the cross product. 它不需要叉积。

So now we see we're on the completely wrong track. 所以现在我们看到我们走在完全错误的轨道上。

When we want to take a "producty" combination, I find the most natural way is to use a list comprehension. 当我们想采用“生产性”组合时,我发现最自然的方法是使用列表理解。 So let's just do that instead. 因此,让我们改为这样做。

makeTupleList (a,b) = let funs = [(+2),(\x->x-2)]
                      in [(f a, g b) | f <- funs, g <- funs]

And that seems to do it. 这似乎做到了。

*> makeTupleList (10,20)
[(12,22),(12,18),(8,22),(8,18)]

I would drop the ZipList: 我会删除ZipList:

makeTupleList :: (Int, Int) -> [(Int, Int )]
makeTupleList (a,b) = (,) <$> aList <*> bList
 where
  functionList :: [Int -> Int]
  functionList = [flip (-) 2  ,(+ 2) ]
  aList :: [Int]
  aList = functionList <*> [a]
  bList = functionList <*> [b]

Yielding: 屈服:

 λ> makeTupleList (1,1)
 [(-1,-1),(-1,3),(3,-1),(3,3)]

ZipList is for not generating permutations out of an applicative action. ZipList用于不根据应用动作生成排列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM