top page > computer > haskell > web_lecture > for_programmer > iomcn_greeting.html
更新日:
文責: 重城良国

IOMcn型: 秒針の偶奇であいさつを変える

(工事中 60%)

はじめに

ここまでのインターフェースで入力値や出力値についていろいろといじることはできる。しかし、出力の値によって機械を選ぶことはできない。秒針の偶奇であいさつを変える例を見ながら必要な追加で必要な機械を紹介する。

仕様

偶数の秒には"olleh"を奇数の秒には"hello"を表示する機械を作る。今が偶数の秒であることを確認する機械は用意した。

isEven :: IOMcn () Bool

機械isEvenを動かしてみよう。

% ghci IOMcn.hs
*IOMcn> runIOMcn isEven
(その時によってTrueかFalseが表示される)True
*IOMcn> runIOMcn isEven
False

関数message

greeting.hs

関数messageは引数によって違う機械を返す関数だ。Bool値をとり

それぞれ返す関数だ。定義は

message :: Bool -> IOMcn String ()
message True = arr reverse >>> putLine
message False = putLine

となる。モジュールIOMcnを使うのでファイルの先頭に

import IOMcn

を追加したうえで関数messageの定義を書きこもう。

% ghci greeting.hs
*Main> runIOMcn $ arr (const "hello") >>> message False
hello
*Main> runIOMcn $ arr (const "hello") >>> message True
olleh

どうつなげればいいのか

今あるのは

isEven :: IOMcn () Bool
message :: Bool -> IOMcn String ()

という機械と関数だ。これらをどうつなげれば

機械が作れるだろうか。機械isEvenの出力であるBool値をうけとるためにはBool値を引数としてとる関数messageをBool値を入力とする機械にする必要がある。

arr message :: IOMcn Bool (IOMcn String ())

これと機械isEvenとをつないでみよう。

isEven >>> arr message :: IOMcn () (IOMcn String ())

これらの型を対話環境で確かめてみよう。

*Main> :t message
message :: Bool -> IOMcn String ()
*Main> :t arr message
arr message :: IOMcn Bool (IOMcn String ())
*Main> :t isEven >>> arr message
isEven >>> message :: IOMcn () (IOMcn String ())

うまくいかない

機械を出力する機械がある。

isEven >>> arr message :: IOMcn () (IOMcn String ())

今まで学んできた範囲ではこれ以上はどうすることもできない。

機械app

機械の出力になってしまった機械をどう扱えばいいだろうか。機械mとそれに対する入力値のタプルを入力として機械mの出力を出力とする機械を考える。

app :: IOMcn (IOMcn a b, a) b

これは機械mと値vを入力されると機械mに値vを入力して機械mの出力を出力とする機械だ。この機械を使えばいい。

機械appを使うための準備

機械appを使うには

IOMcn () (IOMcn String ())

ではなく

IOMcn () (IOMcn String (), String)

のような機械が必要になる。この型の機械は

isEven :: IOMcn () Bool

IOMcn Bool (IOMcn String (), String)

のような機械をつなげばいい。さらにこのような型の機械は

Bool -> (IOMcn String (), String)

のような関数にarrを適用すればできる。この型の関数を作るのは簡単だ。関数sayHelloとして定義してみよう。

sayHello :: Bool -> (IOMcn String (), String)
sayHello b = (message b, "hello")

これをgreeting.hsに書きこむ。

組み立てる

対話環境で組み立ててみよう。

*Main> :reload
*Main> :t arr sayHello
arr sayHello :: IOMcn Bool (IOMcn String (), String)
*Main> :t isEven >>> arr sayHello
isEven >>> arr sayHello :: IOMcn () (IOMcn String (), String)
*Main> :t isEven >>> arr sayHello >>> app
isEven >>> arr sayHello >>> app :: IOMcn () ()
*Main> runIOMcn $ isEven >>> arr sayHello >>> app
(時間によってhelloまたはolleh)hello

関数greetingの定義は

greeting :: IOMcn () ()
greeting = isEven >>> arr sayHello >>> app

機械isEvenはBool値を出力する。機械arr sayHelloはBool値を入力し「文字列を入力値とする機械」と文字列とを出力する機械だ。関数appは機械mと値xを入力し値xを機械mに入力したときの出力を出力とする機械だ。機械greetingの定義をgreeting.hsに書きこむ。

*Main> :reload
*Main> runIOMcn greeting
hello
*Main> runIOMcn greeting
olleh

まとめ

他の機械の出力値によって次の機械を変化させるためには

(>>>) :: IOMcn a b -> IOMcn b c -> IOMcn a c
arr :: (a -> b) -> IOMcn a b

だけでなく機械と値を入力とし値を機械に入力する機械appが必要になる。

app :: IOMcn (IOMcn a b, a) b

「IOMcn型: 普通の関数をつなぐ」へもどる 「IOMcn型: まとめ」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics