理想未来ってなんやねん

娘可愛い。お父さん頑張る。

Haskell 2日目

『ふつうのHaskellプログラミング』2日目。

型と値

静的型チェックと型推論

JavaやCと同じように、Haskellにも静的な型チェックがある。
つまりコンパイル時に処理系が型チェックしてくれる。

JavaやCでは型の宣言が必須だが、Haskellでは型推論という機能があり、型を宣言を省略しても処理系が型を推測して補ってくれるようになっているので、推論の結果、矛盾なく型付けができれば、宣言しなくてもエラーにならない。

たいていのHaskellプログラムは定義に矛盾がない限り、型をまったく宣言しなくてもコンパイルできる。

基本的な型

基本的な型は次の通りらしい。

意味 値の例
Int 整数型 -1,0,1,777
Char 文字 'a', 'A', '\m'
String 文字列 "aaa", "string"
Bool 真偽値 True, False
[○○] ○○のリスト [1, 2, 3]

その他の数値の型については、『6.3 数値』に記載されているようです。

関数の型

Haskellでは引数の型と返り値の型の組み合わせで関数の型を表現するようになっている。

String -> [String]

関数の型は次のように表記される

1引数の型 ->2引数の型 -> .... -> 返り値の型


次は、似ているけど違う

->

と、do式と一緒に使う、

main = do cs <- getContents
          putStr cs 

の『<-』とは別物。
『<-』は変数を値に束縛する(bind)為の構文。

型変数

次の例、

[a] -> Int

上記の例でのaは型変数(type variable)といい、どんな型に置き換えてもよい。
[a]は、aのリストを表す。
型変数を含む型のことを多相型(polymorphic type)と呼ぶ。

複数の型変数

1つの型に型変数が2つ以上登場する場合もある。

(a -> b) -> [a] -> [b]
型の宣言

明示的に型を宣言する場合は次のような書き方をする。

firstNLines :: Int -> String -> String
firstNLines n cs = unlines $ take n $ lines cs 


明示的に変数の型を宣言するには『::』を使う。

関数名 ::1引数の型 ->2引数の型 -> .... -> 返り値の型

型推論があるので型を宣言しなくても使えるが、できれば宣言した方がよい。
理由は、

  • 情報量が増え、ソースコードが読みやすくなる。
  • 型変数を大量に使った複雑なコードでは型推論が失敗する事がある。


今日のところはこんな感じで。

思った事

Haskellって右向きな言語?

返り値の型が一番右にくる点とか見ていると、見ているだけで思考が右へ右へよっていきます。

関数名 ::1引数の型 ->2引数の型 -> .... -> 返り値の型

今まで使用していた言語だと、代入は右から左だし、返り値の型が一番左。
Haskellが右向きな言語であれば、左向きな言語ってことだろうか。
考えたことなかった。


ググってみるとじじぃさんという方がこんな事を書いてました。

  • [OCaml][Haskell]strict な言語では左向き、lazy な言語では右向きが偉い

fold の話。厳密には言語というより、リストが正格か遅延かって話だと思うけど。

ともあれ、OCaml 使いなら List.fold_right より、末尾再帰な List.fold_left を好んで使うに違いない……と思う。 逆に Haskell の場合は foldl より foldr を使った方が良いらしいが、どうしてなのかはピンと来てない。 なんでだろう。

他の関数型言語とか知らないので断言できませんが、lazyな言語は右向きなのかもしれません。

返り値?戻り値?

ところでこの本、表記が『戻り値』ではなく『返り値』で統一されているみたいで違和感があった。
英語でかくとどちらも『return value』だったら一緒だよね?
Haskellだと違うのかとか、いろいろ考えてしまった。


今日のところはここまで