Tosainu Lab

すごいH本を読み始めた

ヾ(❀╹◡╹)ノ゙

数日前からすごいH本ことすごいHaskellたのしく学ぼう!を読み始めました.
以前から読んでみたいなと思っており, 学校図書館にお願いしてみたところ入れてもらえました. ありがたい.

以来3ヶ月以上この本を借りていた1のですが, 学校の勉強が忙しかったり, 複数のプログラミング言語に手を出すのはアレだよなぁと思いながら結局1ページも読んでいませんでした.
しかし, 春休み後半に入り, こういう問題のうまい解決案の模索に嫌気が2差して_(:3 」∠)_していたため, 気分転換にと読み始めました.

”すごいHaskell楽しく学ぼう!” の感想

現時点でまだ5章までしか読めていないのですが, それでもこの本はとてもわかりやすく, 何より楽しいと断言できます.

というのも, 僕がHaskellに手を出すのはこれが初めてではなく, 2013年秋のプログラミング言語の選択に迷っていた時期から何度かHaskell本を読んでは諦めていました.
例えばその時読んだ本の一つであるReal World Haskell―実戦で学ぶ関数型言語プログラミングは “3章-型を定義し、関数を単純化する” あたり(だったと思う)からの急なレベルの上昇に挫折, Software Design 2010年6月号の関数型言語特集はHaskellに対する興味を高めることができたものの, 言語の入門としては情報不足でした.

それに対しこの本は, イントロダクションのGHCi3の使い方に始まり, 1章の関数の定義, リスト, タプル, 2章の, 3章のリスト/タプルのパターンマッチガード式等, 4章の再帰関数, そして5章の高階関数といったように, Haskellにとっての基本的なことから(訳者序文の言葉で)ファンシーなイラストと共に軽妙な語り口で解説しており, 非常にわかりやすく, 何より読んでいて楽しいのです.

本当に今まで読んだHaskell本とは全く違いました. 今は図書館で借りていますが, いずれはMy H本を入手せねばなと思っています.

”Haskell” に対しての感想

いやぁ, Haskell強い! 想像を超える強さがこの言語にはありました.
いわゆる一目惚れってやつです. 元々C++を勉強していたことをふまえると浮気みたいな感じですが…

とりあえず, この数日で勉強した中から強いなと思ったものをいくつか挙げてみます.

文法的な面

とてもシンプルで, 普段書いているC++と比べると打ちやすい言語だと思います.
例えば, 数値を1つ受け取ってその2倍を返す関数twiceをC++14で書くとこんな感じになりますが,

template <typename T>
constexpr auto twice(T x) {
  return x * 2;
}

Haskellではこう

twice :: (Num a) => a -> a
twice x = x * 2

また, カリー化の考え方を使えば

twice :: (Num a) => a -> a
twice = (*2)

みたいに書けるらしいです.

あのラムダ式も…

[](auto x, auto y) {
  return x + y;
}
\x y -> x + y

めっちょシンプル.

単に打ち込む文字数が少ないだけでなく, (){}といった一般的なキーボードで**Shift + □**のようにしないと打ち込めない文字列が少なくて済むのも気に入りました.

リスト

リストは同じ型の要素を複数格納するデータ構造, 普段使っている言葉だと配列みたいなものでしょうか.
文法としてはこんな感じ.

[1, 2, 3, 4, 5, 6, 7, 8, 9]

["foo", "bar", "baz", "qux"]

本当にすごいのはここからで, 例えば列挙できる要素の組み合わせでリストを作るレンジ

[1..5] -- => [1,2,3,4,5]

[1,3..19] -- => [1,3,5,7,9,11,13,15,17,19]

['A'..'Z'] -- => "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

Haskellの遅延評価を活かした無限リスト

-- take は先頭からn個分の要素のリストを返す関数

take 3 [1..] -- => [1,2,3]

ある集合から別の集合を作るリスト内包表記

take 10 [x * 2| x <- [1..]] -- => [2,4,6,8,10,12,14,16,18,20]

take 10 [x | x <- [1..], x `mod` 3 == 0] -- => [3,6,9,12,15,18,21,24,27,30]

とにかく強い.

ガード

3の倍数が渡されたらFizz, 5の倍数が渡されたらBuzz, 3と5の公倍数が渡されたらFizzBuzzを返す, いわゆるFizzBuzzっぽいことをする関数を, C++でもおなじみなifを使って書いてみる.

fizz x = if x `mod` 15 == 0
           then "FizzBuzz"
           else
             if x `mod` 3 == 0
               then "Fizz"
               else
                 if x `mod` 5 == 0
                   then "Buzz"
                   else show (x)

うーん…

でもこれを, ガードを使って書きなおしてみる.

fizz x
  | x `mod` 15  == 0  = "FizzBuzz"
  | x `mod`  3  == 0  = "Fizz"
  | x `mod`  5  == 0  = "Buzz"
  | otherwise         = show (x)

めっちょCool.

∩(>◡<*)∩

まだすごいところはいっぱいあるけど, 今回はこの辺で.
ではではー.

Footnotes

  1. 延滞ではなく延長です

  2. 半月くらいundefined reference to ~ とかmultiple definition of ~ といったLinker errorばかりに遭遇していたもんで… 原因は単純なんだけどなぁ

  3. Haskellのインタプリタ