Haskellのお勉強(1) Hello, World!

Hello, World!

唐突にHaskellに手を出してみた。GHCのインストールしたんで、まずはハロワから。

main = do
    putStrLn "Hello, World!"

GHCには普通のコンパイラghcコマンドのほかにghciやrunghcがあるけど、ちょこちょこっと試すだけなんでrunghcを使っていくよ。

~/haskell$ runghc hello.hs
Hello, World!
~/haskell$

お、動いた動いた。

コマンドライン引数

お次はもうちょっと複雑なの。

import System.Environment   

add x y = x + y

main = do
    args <- getArgs
    let n = read(args !! 0)
    let m = read(args !! 1)
    print n
    print m
    print (add n m)

!!はn番目の要素を取り出す演算子だって。最初見たときさっぱり分からなかったよ。readは文字列から数値への変換。

~/haskell$ runghc test.hs 123 456
123
456
579
~/haskell$
階乗の計算

階乗の計算行ってみるよ。

import System.Environment   
import Text.Printf

fact 0 = 1
fact n = n * fact(n-1)

factOne n =
    printf "%2d! = %d\n" n ((fact n)::Int)

main = do
    args <- getArgs
    let n = read(args !! 0)
    mapM_ factOne [1..n]

C言語とおんなじ感じでprintfが使えるんだね。これは便利。

~/haskell$ runghc fact.hs 5
 1! = 1
 2! = 2
 3! = 6
 4! = 24
 5! = 120
~/haskell$

Haskellに慣れてないんでどう書くのが正しいのか良く分からないよ。記述の仕方を間違えたときに表示されるメッセージの解読も難しいし。

リスト操作

ちょっとしたリスト操作の例。コマンドライン引数のリストを一個ずつ表示してる。

import System.Environment   
import Text.Printf

one (x,y) = do
    printf "args[%d] = %s\n" (y::Int) x

main = do
    args <- getArgs
    let z = zip args [0..]
    mapM one z

[0..]で[0,1,2,3,...]って無限に続くリストを作れる。でもこの評価は遅延されるんで実際に無限個の数字が並んだリストができちゃうわけじゃないんだってさ。この辺はHaskell独特だね。

~/haskell$ runghc test5.hs abc def 123 1.5
args[0] = abc
args[1] = def
args[2] = 123
args[3] = 1.5
~/haskell$
無名関数

一個上のプログラムを無名関数で書き直してみたよ。

import System.Environment   
import Text.Printf

main = do
    args <- getArgs
    mapM (\(x,y) -> printf "args[%d] = %s\n" (y::Int) x) $zip args [0..]
雑感

Haskellをちょっと触ってみただけだけど、ここまでの雑感。

  • 他の言語のようなループ処理がない
  • 変数は書き換えられない
  • 入出力が独特

副作用を排除した純粋関数型言語ってことらしいけど、慣れるまでに時間が掛かりそうだな。今んとこの理解じゃある程度以上のプログラムを作るのは難しそう。IOモナドとか何者なのか良く分からないし。時間かけてちょっとずつ理解してくかな。