这个问题的标题可能听起来有误导性,但我不确定如何解释我想要做的事情。
我正在尝试使用非确定性数据结构。我正在尝试生成一组部分应用运算符和元组列表的所有可能组合:
-- test.hs
makeTupleList :: (Int, Int) -> [(Int, Int)]
makeTupleList (a, b) = ZipList [(+2), (-2)] <*> ZipList [a, b]
我希望makeTupleList
返回类似的内容:
[(a + 2, b + 2), (a + 2, b - 2), (a - 2, b + 2), (a - 2, b - 2)]
但我显然做错了,因为我一直收到这个错误:
Couldn't match type `ZipList' with `[]'
我如何得到我想要的结果?
答案 0 :(得分:4)
您声明的类型与该函数实际具有的类型不匹配。
让我们只检查函数的主体
*> :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!那根本不好。
所以让我们修复错误。第一个错误是-2
绊倒了你,因为它解析为负2,而不是操作符部分。
你可以通过类型检查看到那个片段:
*> :t (-2)
(-2) :: Num a => a
好的,我们将其更改为显式的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
现在我们看到了概念错误(如果你测试它,你可以看到更多)。我们刚刚回来[a+2,b-2]
。 ziplist 的作用 - &#34;拉链&#34;列表在一起。它没有采用交叉产品。
现在我们看到我们处于完全错误的轨道上。
当我们想采取&#34;产品&#34;组合,我发现最自然的方式是使用列表理解。所以,让我们这样做吧。
makeTupleList (a,b) = let funs = [(+2),(\x->x-2)]
in [(f a, g b) | f <- funs, g <- funs]
这似乎就是这样。
*> makeTupleList (10,20)
[(12,22),(12,18),(8,22),(8,18)]
答案 1 :(得分:4)
我会放弃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]
产量:
λ> makeTupleList (1,1)
[(-1,-1),(-1,3),(3,-1),(3,3)]
ZipList用于不从应用操作中生成排列。