Workshop/MiracleHaskell/015
日時
2012/09/28
内容
http://learnyouahaskell.com/input-and-output のreturnについての説明あたりから再開します。
宿題
前回、以下のような
- 演算子
- 左辺値
- 右辺値
の3つの値を入力すると、計算結果が得られるCalcというプログラムを作りました。
func :: String -> Int -> Int -> Int
func "+" = (+)
func "-" = (-)
func "*" = (*)
func "/" = div
func _ = error "*** Error: not operator"
main :: IO ()
main = do
f <- getLine
a <- getLine
b <- getLine
putStrLn $ "Answer: " ++ show (func f (read a) (read b))
このプログラムを改造して、空行が入力されるまで計算を繰り返すようにしてください。
$ ./Calc
+
10
20
Answer: 30
-
1
9
Answer: -8
*
4
5
Answer: 20
/
100
$
ヒント
- 再帰を使うかもしれません
- foreverという関数を使うと楽かもしれません
ごめんなさい
ちょっとむづかしかったですね。。。 この本ではexit例外を習わないので、この宿題はIOモナドを大域脱出せずに解くことになってしまいます。 exitさえ使えば以下のように簡単に解けるのですが。。。
import System.Exit
import Control.Monad
func :: String -> Int -> Int -> Int
func "+" = (+)
func "-" = (-)
func "*" = (*)
func "/" = div
func _ = error "*** Error: not operator"
getLineEmptyExit :: IO String
getLineEmptyExit = do
s <- getLine
when (s == "") exitSuccess
return s
main :: IO ()
main = forever $ do
f <- getLineEmptyExit
a <- getLineEmptyExit
b <- getLineEmptyExit
putStrLn $ "Answer: " ++ show (func f (read a) (read b))
例外による大域脱出を使わないと、以下のようにモナド変換子を使わければなりません。 これはまたの機会に。。。
import Control.Monad
import Control.Monad.Trans.Maybe
import Control.Monad.IO.Class
func :: String -> Int -> Int -> Int
func "+" = (+)
func "-" = (-)
func "*" = (*)
func "/" = div
func _ = error "*** Error: not operator"
getLineEmptyExit :: MaybeT IO String
getLineEmptyExit = do
s <- liftIO getLine
if s == ""
then MaybeT $ return Nothing
else return s
calc :: MaybeT IO ()
calc = do
f <- getLineEmptyExit
a <- getLineEmptyExit
b <- getLineEmptyExit
liftIO $ putStrLn $ "Answer: " ++ show (func f (read a) (read b))
main :: IO ()
main = do
runMaybeT $ forever calc
return ()