とりあえず型を合わせるHaskell入門
初心者による初心者のためのHaskell。 *1
そこそこ需要がある内容ではある気がしてる。
このエントリを読むのに最低限な知識
ghciを起動。
Prelude> :t 'c' 'c' :: Char
式の型をを調べるには、
:t 式
と入力します。
Prelude> :t 1 1 :: Num a => a
型制約です。
「1 はaという型を持つ、ただしaはNumという型クラスのインスタンス」
と読む。
Prelude> :t \x -> x `div` 2 \x -> x `div` 2 :: Integral a => a -> a
関数型は a -> b という風に書きます。
型を合わせるテクニック その1 「普通に書く」
普通に書けば普通は型が合います。さもなくば、普通に型があってない。
型を合わせるテクニック その2 「IOをマスター(?)」
初心者が苦戦する壁「IO」。
main :: IO () main = putStrLn "hello, world"
基本中の基本、hello, worldです。
ところで、真似する場合、ここからはファイルに書いてghcでコンパイルしてください。
ちょっと変えてみよう。
main :: IO () main = do putStrLn "h = llo"
doをつけても通ります。
doを付けると、型が変わると思っていませんでしたか?そうでもないみたいです。
端的に言うとdoは、複数の命令をまとめて、IO hogeにする。(この場合、hogeは()型)
これも通ります。
main :: IO () main = do putStrLn "hello" putStrLn "moja" putStrLn "huga"
doにはもうひとつ役割がある。
doの中では、次のように、「IOを剥がす」ことができる。
main :: IO () main = do line <- getLine putStrLn line
「IOを剥がす」とは...
getLine :: IO String
line :: String
こういうことです。
次はif文の例。
main :: IO () main = do line <- getLine if read line == 0 then do putStrLn "hello" putStrLn "hello" else putStrLn "f*ck"
then のあとのdoは必要ですよ。2つのputStrLnをまとめる。
else のあとには要らないのは、1つだから。
else節を空にしたい。どうやりますか?
main :: IO () main = do line <- getLine if read line == 0 then putStrLn "hello" else return ()
returnを使う。
hoge :: a の時、
return hoge :: IO a
になるみたいです。
in other words,
return :: a -> IO a *2
型を合わせるテクニックその3 「型注釈」
こんなのを書いてみる。
Prelude> :t do { line <- getLine; return $ read line } do { line <- getLine; return $ read line } :: Read b => IO b
(ここからはまたghciです)
そういえば、doの書き方、こういうふうにも書けるみたい。
Read bってなんやねん。型クラスムズイ。僕はreadIntを作ったんだよ。
そういうときは、型注釈を使う。
Prelude> :t do { line <- getLine; return $ (read line :: Int) } do { line <- getLine; return $ (read line :: Int) } :: IO Int
OK.
不要な多相を消し去ると、型エラーが読みやすくなるので良いです。 *3
ところでこの型注釈演算子(演算子ではない?)結合の強さが謎いので注意