第9章 対話プログラム #6

9.9 練習問題

  1. エラーの際に単にビープ音を鳴らすのではなく、エラーの位置が分かるように電卓を変更せよ。パーサーは消費しなかった文字列を返すという性質を活用するとよい。

「エラーの位置がわかるように」というのが何を求めているのかよくわからないが、「消費した(解読できた)位置まで戻る」という仕様にすることにした。

@@ -1,4 +1,4 @@
-module NineSix where
+module NineNineTwo where
 
 import Parsing
 import Expr
@@ -58,9 +58,9 @@
 
 eval    :: String -> IO ()
 eval xs =  case parse expr xs of
-             [(n,"")] -> calc (show n)
-             _        -> do beep
-                            calc xs
+             [(n,"")]  -> calc (show n)
+             [(_,out)] -> do beep
+                             calc (take (length xs - length out) xs)
 
 clear :: IO ()
 clear =  calc ""

要するにevalのパターンマッチを書き換えて、消費しなかった文字を切り捨てて再表示している。

カッコが多いのがHaskellっぽくないのはわかっているけど、take (length xs - length out) xsが簡潔にならない限り、

calc $ take (length xs - length out) xs

にしたところでたいした違いはない。