ようこそ。睡眠不足なプログラマのチラ裏です。

Haskellのお勉強 その1

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門

ふつける」やら「ふつハス」の愛称で親しまれている「ふつうのHaskellプログラミング」を買いました。
というわけで、関数型プログラミングHaskellのお勉強をのんびりはじめます。


はじめてのHaskell

はじめての言語の勉強と言えば、
まずはお約束という感じで「こんにちは世界」です。

{-Hello World!-}
main = putStrLn "Hello World!"


Haskellのすべての始まりはmainから。そしてmainが終わるとプログラムは終了する。
「main =」ってのは変数の定義を意味していて、イコールの左が変数でイコールの右が値という感じ。
ここで注意すべき点は、変数mainの値は関数ではなくって、アクション(action)である点。
Haskellで言う「アクション」とは具体的にはなんなのかってのは、ふつハス11章で解説されるとのこと。


「putStrLn "Hello World!"」の部分は、putStrLn関数に引数 "Hello World!"を渡しているんだが、
Haskellでは、"Hello World!"にputStrLn関数を適用する(apply)と言うらしい。


ちなみにghcによるコンパイルは、下記のように記述 [-o]オプションはexeに任意の名前を付けたい場合にどうぞ。
[-o]オプションを省略すると main.exeというファイル名でコンパイルされる。

C:\haskell\src>ghc hello.hs -o hello

あるいは、--makeオプションを使ってファイル名と同じ名称でコンパイルすることもできる。

C:\haskell\src>ghc --make hello.hs


簡易なUNIXコマンドの模倣とか

{-cat-}
main = do cs <- getContents
          putStr cs

ここで出てきた「<-」の記述についてだが、
上記のような場合、「変数csをgetContentアクション(値)に束縛する」と言うらしい。
このとき、getContentアクションは評価遅延されて、束縛された変数csがputStrに渡されたときに
はじめてアクションが評価される。そして、変数csの値にputStr関数を適用して、アクションが実行される。
また、「do式」によって、アクションの実行順序を指定することができる。
「do式」を用いない場合、上から下の順にアクションが実行されるとは限らない。
「do式」を用いる場合、インデントを揃えることで式が同じブロックであることが表現される。
この規則をレイアウト(layout)あるいはオフサイドルール(off-side rule)と呼ぶ。

{-countline-}
main = do cs <- getContents
          print $ length $ lines cs
{-head-}
main = do cs <- getContents
          putStr $ firstNLines 10 cs
firstNLines n cs = unlines $ take n $ lines cs
{-tail-}
main = do cs <- getContents
          putStr $ lastNLines 10 cs
lastNLines n cs = unlines $ takeLast n $ lines cs
takeLast n ss = reverse (take n (reverse ss))
{-countbyte-}
main = do cs <- getContents
          print $ length cs
{-countword-}
main = do cs <- getContents
          print $ length $ words cs

無名関数

無名関数は以下の様に「¥」と「->」を使って定義する。
「¥」の後に仮引数を並べて書き、「->」の後に本体を書く。

{-for example-}
\ x y -> x + y
{-head (無名関数を利用)-}
main = do cs <- getContents
          putStr $ (\n cs -> unlines $ take n $ lines cs) 10 cs
{-tail (無名関数を利用)-}
main = do cs <- getContents
          putStr $ (\n cs -> unlines $ (\n ss -> reverse $ take n $ reverse ss) n $ lines cs) 10 cs