我试图通过编写简单的棋盘游戏来学习Haskell。它显示一个棋盘,并从SAN notation中的标准输入移动。这是我到目前为止所得到的:
import System.IO
import Chess
import Chess.FEN
main = do
putStrLn "Welcome to Console Chess!"
putStrLn $ show defaultBoard
gameLoop defaultBoard
gameLoop board = do
putStr "Your move: "
hFlush stdout
move <- getLine
let newBoard = moveSAN move board
case newBoard of
Left _ -> do
putStrLn "Invalid move, try again..."
gameLoop board
Right b -> do
putStrLn $ show b
gameLoop b
问题是对moveSAN
功能的调用有时会使程序崩溃,从而失去游戏中取得的所有进展。例如,在&#34;您的行动中按Enter键:&#34;提示产生:
Your move:
cchess: Prelude.head: empty list
否则,输入两位数字会产生:
Your move: 11
cchess: Error in array index
输入两个句点给出:
Your move: ..
cchess: Char.digitToInt: not a digit '.'
我想捕获这些错误并告知用户他们输入的移动不是有效的SAN表示法。我怎么能这样做?
答案 0 :(得分:7)
在理想的世界中,你会避免像head
这样的函数而根本没有运行时错误。运行时错误从根本上很尴尬,尤其是在Haskell中。
在这种情况下,您希望捕获运行时错误。如果您要将其转换为Maybe
,则可以使用spoon
包。
由于懒惰,Haskell的异常是微妙的。特别是,如果你不评估具有例外的结构部分,它就不会被激发。这在spoon
处理,具有两个不同的功能:
spoon
,它深入评估结构 但需要特殊类型类的实例teaspoon
仅评估您的weak head normal form 对于您的情况,我认为teaspoon
应该没问题。尝试使用以下方法检查解析结果:
teaspoon (moveSAN move board)
应该为您提供Maybe
值。
如果这不起作用,则意味着您需要评估更多结构以达到异常。看起来Board
没有实现使用spoon
对其进行深度评估所需的类型类,所以最好的选择是有点hacky:对spoon
的结果使用show
:
spoon (show $ moveSAN move board)
这会给你一个Maybe String
。如果是Just
,则移动正确解析;如果是Nothing
,则会出错。
值得注意的是spoon
软件包确实做不了多少:它所拥有的每个函数只有a couple of lines。在某些时候,值得弄清楚如何自己处理Haskell中的异常,但是现在spoon
只是更方便一点,应该适合你。