如何实现更改数组单元的功能,从而避免Haskell中的非穷尽模式错误? [英] How to implement a function to change array cells avoiding non-exhaustive pattern errors in haskell?

查看:160
本文介绍了如何实现更改数组单元的功能,从而避免Haskell中的非穷尽模式错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是编写一个名为walk的函数,该函数将迷宫单元格的值与其邻居切换. 例如,调用walk 0 labyrinthA应该将T个单元格向左移动.在这里我尝试更改ghci中迷宫细胞的值.

My goal is to write a function called walk, which switches the value of a labyrinth cell with its neighbour. For example calling walk 0 labyrinthA should move the T one cell to the left.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"向左走走0迷宫A.

Now i tried to let the 'T' walk to the left with 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是整数.
在此处输入图片描述

Where as yKoord and xKoord are integers.
enter image description here

推荐答案

您收到的错误是因为这些模式无法涵盖所有​​情况. 穷举模式是一种穷尽所有可能性的模式,即为每个潜在输入值返回结果.

The error you’re getting is because the patterns don’t cover every case. An exhaustive pattern is one that exhausts all the possibilities, that is, returns a result for every potential input value.

在这里,如果您打个电话,例如labyrinthA 10 1,会发生什么?还是labyrinthA 0 0?如果编译器在编译时未向您发出有关此错误的警告,则可能需要使用-Wall标志进行编译以打开警告.

Here, what would happen if you called, for example, labyrinthA 10 1? Or labyrinthA 0 0? If your compiler is not warning you about this bug at compile time, you might want to compile with the -Wall flag to turn warnings on.

如果程序逻辑不允许用任何其他值调用该函数(在这种情况下,它可能应该是只能从一个位置调用的局部函数),则可以快速解决.在函数底部添加如下一行:

If the program logic makes it impossible to call the function with any other values (in which case it should probably be a local function that can only be called from one place), there is a quick fix. Add a line like this to the bottom of your function:

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

这将添加一个包罗万象的子句,以匹配尚未涵盖的任何模式,从而使编译器满意.如果确实使用不可能的"值调用了该函数,则逻辑错误现在将通过更具信息量的调试消息使程序崩溃.

This adds a catch-all clause matching any patterns that haven’t been covered already, satisfying the compiler. If the function does get called with "impossible" values, the logic error will now crash the program with a more-informative debug message.

在您的情况下,您未向我们展示的程序的其他部分会使用函数域之外的值来调用函数,这会导致运行时崩溃.不幸的是,我们无法在看不到代码的情况下为您提供帮助,但是要跟踪导致崩溃的呼叫顺序将是一个不错的第一步.

In your case, some other part of your program that you haven’t shown us calls your function with values outside its domain, which is giving you a runtime crash. Unfortunately, we cannot help you without being able to see the code, but tracing what sequence of calls led to the crash would be a good first step.

在这种特定情况下,您可能不想每次玩家迈出一步时都更新迷宫的地图.用功能性语言进行操作并不是非常有效或优雅的操作.相反,您可以存储不可变的地图,然后更新播放器的位置以在其上方绘制. (X,Y)坐标可以是另一个参数,也可以是您传递的程序状态数据的一部分.

In this specific instance, you probably don’t want to update the map of your labyrinth every time the player takes a step. That’s not a very efficient or elegant operation in a functional language. You might, instead, store the immutable map and then update the position of your player, to draw on top of it. The (X,Y) coordinates could be another parameter or part of program-state data that you pass around.

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

This doesn’t answer your question about modifying a function after it’s been defined. I think that’s an XY problem, but here’s a literal answer to that part of the question. You cannot do this with the String type. There are ways to get mutable state in Haskell, such as a mutable Data.Vector.MVector with the ST type, but that’s not your immediate problem.

这篇关于如何实现更改数组单元的功能,从而避免Haskell中的非穷尽模式错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆