如何实现一个函数来更改数组单元格以避免 haskell 中的非详尽模式错误?

How to implement a function to change array cells avoiding non-exhaustive pattern errors in haskell?

我的目标是编写一个名为 walk 的函数,它可以切换迷宫单元与其相邻单元的值。 例如调用 walk 0 labyrinthA 应该将 T 向左移动一个单元格。Here i tried to change a value of a labyrinth cell in ghci.

showLabyrinth labyrinth =
   putStrLn $ unlines $ [[labyrinth j i | i <- [1..dimH]] | j <- [1..dimV]]
 where
   dimH = length . takeWhile (/='O') $ [labyrinth 1 i | i <- [1..]]
   dimV = length . takeWhile (/='O') $ [labyrinth i 1 | i <- [1..]]

labyrinthA 9 _  = 'O'
labyrinthA _ 16 = 'X'
labyrinthA _ 17 = 'O'
labyrinthA 1 _  = 'X'
labyrinthA 2 1  = 'X'
labyrinthA 2 8  = 'X'
labyrinthA 2 12 = 'X'
labyrinthA 2 _  = ' '
labyrinthA 3 1  = 'X'
labyrinthA 3 3  = 'X'
labyrinthA 3 5  = 'X'
labyrinthA 3 6  = 'X'
labyrinthA 3 8  = 'X'
labyrinthA 3 9  = 'X'
labyrinthA 3 10 = 'X'
labyrinthA 3 12 = 'X'
labyrinthA 3 14 = 'M'
labyrinthA 3 _  = ' '
labyrinthA 4 1  = 'X'
labyrinthA 4 2  = 'X'
labyrinthA 4 3  = 'X'
labyrinthA 4 5  = 'X'
labyrinthA 4 6  = 'X'
labyrinthA 4 12 = 'X'
labyrinthA 4 _  = ' '
labyrinthA 5 1  = 'X'
labyrinthA 5 5  = 'X'
labyrinthA 5 8  = 'X'
labyrinthA 5 9  = 'X'
labyrinthA 5 10 = 'X'
labyrinthA 5 12 = 'X'
labyrinthA 5 13 = 'X'
labyrinthA 5 15 = 'X'
labyrinthA 5 _  = ' '
labyrinthA 6 1  = 'X'
labyrinthA 6 3  = 'X'
labyrinthA 6 4  = 'X'
labyrinthA 6 5  = 'X'
labyrinthA 6 7  = 'X'
labyrinthA 6 8  = 'X'
labyrinthA 6 10 = 'X'
labyrinthA 6 _  = ' '
labyrinthA 7 1  = 'X'
labyrinthA 7 6  = 'T'
labyrinthA 7 9  = 'X'
labyrinthA 7 10 = 'X'
labyrinthA 7 11 = 'X'
labyrinthA 7 12 = 'X'
labyrinthA 7 13 = 'X'
labyrinthA 7 14 = 'X'
labyrinthA 7 15 = 'X'
labyrinthA 7 _  = ' '
labyrinthA 8 6  = 'E'
labyrinthA 8 _  = 'X'

现在我试着让 'T' 向左走 walk 0 labyrinthA

walk direction labyrinth | direction == 0 = let labyrinth (yKoord 'T') 
(xKoord 'T') = ' ' && let labyrinth (yKoord) ((xKoord+1)) = 'T'
                          | direction == 1 = undefined
                          | direction == 2 = undefined
                          | direction == 3 = undefined 

其中 yKoord 和 xKoord 是整数。
enter image description here

您遇到的错误是因为模式并未涵盖所有情况。 穷举 模式是穷尽所有可能性的模式,即 returns 每个潜在输入值的结果。

在这里,如果您调用 labyrinthA 10 1 会发生什么情况?还是labyrinthA 0 0?如果您的编译器没有在编译时就此错误向您发出警告,您可能需要使用 -Wall 标志进行编译以打开警告。

如果程序逻辑使得无法使用任何其他值调用该函数(在这种情况下,它可能应该是一个只能从一个地方调用的本地函数),有一个快速修复方法。在函数底部添加这样一行:

labyrinthA x y = error $ "Domain error: labyrinthA " ++ show x ++
                         " " ++ show y

这添加了一个包罗万象的子句,匹配任何尚未涵盖的模式,满足编译器的要求。如果函数确实以“不可能”的值被调用,逻辑错误现在将使程序崩溃,并显示一条信息更丰富的调试消息。

在您的情况下,您未向我们展示的程序的其他部分使用其域外的值调用您的函数,这会导致运行时崩溃。不幸的是,我们无法在无法查看代码的情况下为您提供帮助,但追踪导致崩溃的调用顺序将是很好的第一步。

在这个特定实例中,您可能不希望玩家每次迈出一步时都更新迷宫地图。在函数式语言中,这不是一个非常有效或优雅的操作。相反,您可以存储不可变地图,然后更新播放器的位置,以在其上绘制。 (X,Y) 坐标可以是您传递的另一个参数或程序状态数据的一部分。

这没有回答您关于在定义函数后修改函数的问题。我认为这是一个 XY 问题,但这是对这部分问题的字面答案。您不能使用 String 类型执行此操作。有一些方法可以在 Haskell 中获取可变状态,例如具有 ST 类型的可变 Data.Vector.MVector,但这不是您的直接问题。