在Haskell中有条件地更改元组元组中的值

时间:2015-09-25 16:36:59

标签: list haskell tuples element

我正在处理3元组的3元组((a,b,c),(d,e,f),(g,h,i))。现在我想把这个元组作为输入,并且输出生成一个元组列表,如果元素有一定的值,元素就会变成一个值。

示例:

changefromtovalue :: a -> a -> ((a,a,a),(a,a,a),(a,a,a)) -> [((a,a,a),(a,a,a),(a,a,a))]

changefromtovalue 1 5 ((0,1,2),(1,2,3),(2,3,4)) results in [((0,5,2),(1,2,3),(2,3,4)),((0,1,2)(5,2,3)(2,3,4))]

现在我没有使用整数,但我认为这个想法保持不变。

首先我认为我想要某种地图,但这会立即改变所有值,而不是每个都改变一个元素的列表。

然后我想,我可以做出所有变化(在示例中[((5,x,x)..),((x,5,x)..),((x,x,5)..)]并以某种方式删除不符合要求的那些,但我无法找到一个干净的方法丢弃不需要的那些。

我已经尝试过搜索并找到了有关为元组制作数据规范的一些信息,但我没有看到它如何真正简化这一特定问题。

转换为列表并使用列表然后转换回来似乎更容易,但它仍然需要一种奇怪的选择。如果可能,我希望避免使用大量转化。

我正在寻找的建议是一种干净的方式,而不是一条完整的代码。

2 个答案:

答案 0 :(得分:2)

根据您在评论中提供的其他信息,我们可以使用Richard Bird的方法解决此问题:

我们将网格表示为列表列表。然后,我们用一个我们可以为它做出的选择列表替换网格中的每个元素。在您的示例中,1变为[1,5](我们选择1或5),n变为[n](对于其他所有内容,没有其他选择)。< / p>

choice                :: Int -> [Int]
choice 1              =  [1,5]
choice n              =  [n]

然后我们为每个元素做出这个选择:

choices               :: [[Int]] -> [[[Int]]]
choices               =  map (map choice)

现在是棘手的部分。我们将选择网格减少为选择的网格,这可以使用列表中的一般笛卡尔积来完成:

cp                    :: [[a]] -> [[a]]
cp []                 =  [[]]
cp (xs:xss)           =  [y:ys | y <- xs, ys <- cp xss]

我们崩溃了一系列选择:

collapse              :: [[[a]]] -> [[[a]]]
collapse              =  cp . map cp

这首先将选择行列表(也就是选择网格)折叠到行选项列表中,然后将行选择列表折叠成行列表选择,也就是选择网格

最后,我们通过首先做出选择然后折叠它们来指定解算器:

solve                 :: [[Int]] -> [[[Int]]]
solve                 =  collapse . choices

例如:

> mapM_ print (solve [[0,1,2],[1,2,3],[2,3,4]])

[[0,1,2],[1,2,3],[2,3,4]]
[[0,1,2],[5,2,3],[2,3,4]]
[[0,5,2],[1,2,3],[2,3,4]]
[[0,5,2],[5,2,3],[2,3,4]]

希望这也证明了如何将元组转换为列表列表使这项任务变得更容易。

注意:有些人可能已经注意到cpsequence列表适用。这意味着我们也可以等同地写:

solve' = sequence . map sequence . choices

答案 1 :(得分:0)

使用元组你必须写:

change x y ((a,b,c),(d,e,f),(g,h,i))
     = ((z a, z b, z c), (z d, z e, z f), (z g, z h, z i))
  where z w = if w == x then y else w

如果使用列表(或数组)来表示3x3网格,生活会更容易。