四則演算
Haskellの型システムが気になって何年かぶりにHaskellを使ってみました。
もう殆ど忘れていたのだけど、一から勉強するよりは楽に使えたのだと思います。
正規表現ライブラリを使って標準入力の引数を四則演算するだけの物を作ってみました。
import Text.Regex.Posix import System.Environment data E = EInt Integer | EVar String | EAdd E E | ESub E E | EMul E E | EDiv E E deriving(Show, Eq) data Tk = TkInt Integer | TkVar String | TkOp String deriving(Show, Eq) main = do v <- getArgs e <- return (head v) print e b <- return (let (c,_) = parse e in c) print b print (eval b) lexx :: String -> [Tk] lexx src = case (src =~ "^[ \n\t\r]*(([0-9]+)|([_a-zA-Z][_a-zA-Z0-9]*)|([+*/\\-]+))" :: [[String]]) of [] -> [] [[k1,_,i,"",""]] -> (TkInt (read i :: Integer)) : (lexx (drop (length k1) src)) [[k1,_,"",id,""]] -> (TkVar id) : (lexx (drop (length k1) src)) [[k1,_,"","",op]] -> (TkOp op) : (lexx (drop (length k1) src)) parse :: String -> (E,[Tk]) parse l = expr (lexx l) expr :: [Tk] -> (E,[Tk]) expr xs = rep(term xs) where rep(x1,(TkOp "+"):xs2) = let (x3,xs3) = term xs2 in rep(EAdd x1 x3, xs3) rep(x1,(TkOp "-"):xs2) = let (x3,xs3) = term xs2 in rep(ESub x1 x3, xs3) rep(x,xs) = (x, xs) term :: [Tk] -> (E,[Tk]) term xs = rep(fact xs) where rep(x1,(TkOp "*"):xs2) = let (x3,xs3) = fact xs2 in rep(EMul x1 x3, xs3) rep(x1,(TkOp "/"):xs2) = let (x3,xs3) = fact xs2 in rep(EDiv x1 x3, xs3) rep(x1,xs1) = (x1,xs1) fact :: [Tk] -> (E,[Tk]) fact ((TkInt i):xs) = (EInt i, xs) fact ((TkVar id):xs) = (EVar id, xs) fact xs = (EInt 0, xs) eval :: E -> Integer eval(EInt a) = a eval(EAdd a b) = (eval a) + (eval b) eval(ESub a b) = (eval a) - (eval b) eval(EMul a b) = (eval a) * (eval b) eval(EDiv a b) = (eval a) `div` (eval b)
*1:Utotch Blog:Haskell で parser を書くには 初心者編 http://utotch.blogspot.jp/2011/12/haskell-parser.html
*2:とりあえず雑記帳:04 attoparsec https://sites.google.com/site/toriaezuzakki/haskell/attoparsec
*3:sirocco の書いてもすぐに忘れるメモ:Haskell の正規表現すげー !!http://d.hatena.ne.jp/sirocco/20090416/1239852340
*4:すぐに忘れる脳みそのためのメモ:Haskell で正規表現 http://jutememo.blogspot.jp/2008/07/haskell.html