IOアクション
(その4)でみた通り、dzenやxmonadの戻り値の型は「IO(なんたら)型」だった。これはIOアクションと呼ばれる。
IOアクションは、「アクション」というだけあって、「何かを実行するもの」を表している。と同時に(なんたら)の部分で結果を生成してくれたりする。
すなわち、IOアクションは2つの事を行う。
「副作用」を生じさせ、その副作用が「結果」を生成する。
これを、先の2つの関数で見てみると以下の通り。
xmonad関数の副作用は、xmonadウインドマネージャを実行する。
生成される結果は無い。
dzen関数の副作用は、パネルのdzenを起動する。
生成される結果は、dzen用の設定を追加したXConfig l型データ。
Haskellで 半沢直樹!
以下の基本的な入出力の関数はIOアクションを返すもので、haskellのhello worldプログラムなんかで使われるもの。コンソールへの表示
putStrLn :: String -> IO ()
コンソールからの入力
getLine :: IO String
この2つの関数で半沢直樹してみる。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
main = do | |
putStrLn "どれくらい怒ってますか?" | |
okorido <- getLine | |
putStrLn ("やられたらやり返す。 " ++ okorido ++ "倍返しだ。") | |
Haskellでスクリプトを実行したい場合はコンソールで
$ runghc io_hanzawa.hs
main、そしてdo
Haskellにおいて、IOアクションの実行は、mainという名前でのみ行われる。
(ただし、ghciを使って対話的環境は、そのまま実行される)
なので、単純に言えば、
main = putStrLn "hello world"
と、一つのIOアクションを定義づけることしかできないが、io_hanzawa.hsの様に、do構文を使うことで複数のIOアクションをひと纏めにして、mainに定義づけることが出来る。
(若しくは、その4みたいに「>>=」演算子で繋ぐ)
またHaskellの構文では、パイソンとかと同様にインデント(段落下げ)に意味があることに注意。do構文の及ぶ範囲もインデントで表されている。
Haskellのコードは、コピペした時にエラーが出たら、インデントもチェックしてみるべし。
IO(なんたら)のなんたらって何?
先に書いたようにIOアクションは実行すると2つの事を行う。
一つが「副作用」、もうひとつが「結果」の生成。
putStrLnの型シグニチャは
putStrLn :: String -> IO ()
であり、実際のコードでは
putStrLn "どれくらい怒ってますか?"
として、使ってみた。
ここでの「副作用」は、画面に
どれくらい怒ってますか?
と表示する事であり。
生成される「結果」は、型シグニチャに示されたIOの次にある()である。
()は見た目の通り空のカッコであり、何もないという結果を返してくれる。
何もない結果というのは分かりにくいので、次のgetLineを見てみる。
型シグニチャは
getLine :: IO String
であり、実際のコードでは
okorido <- getLine
として、「<-」演算子を使っている。
「副作用」は、画面にカーソルが出てリターンキーを押すまでの文字列入力を受け付けること。
一方、生成される「結果」は、画面から入力された文字列である。型シグニチャにあるIOの後ろのStringは、この入力から生成された文字列を示している。
そして、「<-」は 、「結果」のみを名前に結びつける演算子である。
何を言っているかというと、
他の言語では、標準入力からのデータを受け取る関数の戻り値は「文字列」そのものであることが多いので、
okorido = getLine
って感じに書きたくなるが、これはダメだということ。
getLineは、IOアクションを返す関数であり、「結果」である「文字列」そのものを返す関数ではない。
上のイコールを使った式は、単に、getLineと同じことがokoridでも出来るように定義されるだけなのだ。
xmonad.hsをdo構文で
(その4)で見ていたxmonad.hsでは「=<<」演算子を使っていて、その意味はIOなんたら型から、なんたらのみを取り出して、他の関数の引数にするための演算子と説明した。
実は、この役割と同じで直接別の関数の引数にするのではなくて、名前に結びつけるのが「<-」演算子の役割。
do構文を使って書き換えれば以下のようになる。
dzenのIOアクションの「副作用」は、dzen実行ファイルを実行し、画面にステータスバーの表示等を行う。そして、その「結果」は、引数として受け取ったdefaultConfigをベースとして、ステータスバーの表示に必要な加工を行った新しいXConfig l型のデータを生成する。
そして、この結果である、XConfig l型データをconfという名前にバインドし、そのconfを引数としてxmonadを呼び出す。
xmonadのIOアクションの「副作用」は、xmonadウインドマネージャの表示とか管理とかである。そして、結果は空っぽの()である。
というわけで、(その4)の「=<<」演算子を使ったxmonad.hsを
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XMonad | |
import XMonad.Hooks.DynamicLog | |
main = xmonad =<< dzen defaultConfig | |
{ terminal = "urxvt" | |
, modMask = mod4Mask | |
, borderWidth = 3 | |
} |
do構文を使って書き換えれば以下のようになる。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XMonad | |
import XMonad.Hooks.DynamicLog | |
main = do | |
conf <- dzen defaultConfig | |
{ terminal = "urxvt" | |
, modMask = mod4Mask | |
, borderWidth = 3 | |
} | |
xmonad conf |
dzenのIOアクションの「副作用」は、dzen実行ファイルを実行し、画面にステータスバーの表示等を行う。そして、その「結果」は、引数として受け取ったdefaultConfigをベースとして、ステータスバーの表示に必要な加工を行った新しいXConfig l型のデータを生成する。
そして、この結果である、XConfig l型データをconfという名前にバインドし、そのconfを引数としてxmonadを呼び出す。
xmonadのIOアクションの「副作用」は、xmonadウインドマネージャの表示とか管理とかである。そして、結果は空っぽの()である。
0 件のコメント:
コメントを投稿