LoginSignup
2
1

More than 5 years have passed since last update.

Haskell入門ハンズオン! #3: 当日用資料 4/5

Last updated at Posted at 2018-03-09

Haskell入門ハンズオン! #3: 当日用資料 4/5

はじめに

Haskell入門ハンズオン! #3

  • 当日用資料 1/5
  • 当日用資料 2/5
  • 当日用資料 3/5
  • (あとで上記3つをリンクにする)

とみてきた。パーサコンビネータとしての道具はそろった。これで四則演算の式を解析できる。

演算子のパース

はじめに演算子をパースする。演算子をあらわす型シノニムを定義する。

calc.hs
type Op = Integer -> Integer -> Integer

ここでの「演算子」は、「ふたつの整数を引数として、整数をかえす関数」だ。それぞれの演算子用のパーサを定義する。

calc.hs
ad, sb, ml, dv :: Parse Op
ad = char '+' `build` const (+)
sb = char '-' `build` const (-)
ml = char '*' `build` const (*)
dv = char '/' `build` const div

それぞれの記号をパースして、それぞれの演算を結果とするパーサだ。四則演算の演算子は、これら4つの演算子の「どれか」なので

calc.hs
op :: Parse Op
op = ad `alt` sb `alt` ml `alt` dv

対話環境で試してみる。

*Main> :reload
*Main> fromJust (parse op "+") 9 4
13
*Main> fromJust (parse op "*") 9 4
36

関数parseによって得られる関はJust値なので、関数fromJustでなかみの「演算子」を取り出している。取り出された「演算子」(これは関数なので)を数値9, 4に適用した。

式と項

「式」は、ふたつの「項」を演算子でつないだものだ。「項」は、「数」または、「式」を丸括弧でかこったものだ。このように、たがいにたがいの定義に使われているとき「相互再帰の関係にある」という。たとえば「式」の例として、つぎのようなものがある。

13+5, (12*3)+17, (30-5)/(20*4), ((41/2)+3)*5

「項」の例は、つぎのようになる。

19, (25+4), ((11*3)/(25-3)), (((315*8)+31)*7)

式のパース

式のパーサを定義する。

calc.hs
expr :: Parse Integer
expr = (term >@> op >@> term) `build` \((x, o), y) -> x `o` y

パーサtermは、あとで定義する。((x, o), y) -> x o yは関数リテラルだ。引数をパターン((x, o), y)にマッチさせる。ここで、変数xとyにはパーサtermの結果としての「項」の値がはいる。変数oにはパーサopの結果として、演算がはいる。全体の結果としての「x o y」は演算の結果になる。

項のパース

項のパーサを定義する。

calc.hs
term :: Parse Integer
term = number `alt` (char '(' @> expr >@ char ')')

「項」の定義は、つぎのようになる。

「数」または、「式」を丸括弧でかこったもの

パーサtermの定義は、「項」の定義を「そのまま」書けばいい。

できあがり

対話環境で試してみる。

*Main> :reload
*Main> parse expr "3*(5-2)"
9

より使いやすいように関数calcを定義する。

calc.hs
calc :: String -> Maybe Integer
calc = parse expr

対話環境で試す。

*Main> :reload
*Main> calc "3*(5-2)"
9
*Main> calc "(43+24)/(21-16)"
13

ほかの例でも試してみよう。ただし、

  • 空白をいれてはならない
  • 丸括弧は省略できない(余計な丸括弧もいれられない)

というところに注意する。

当日用資料 5/5へ

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1