1. Introduction

Introduction

About this tutorial

  • いろんなサイトに書かれている資料の断片をまとめたものです
  • 命令型プログラミングの経験はあるが、関数型言語の経験がないユーザー向けの資料です

命令型プログラミング - Wikipedia

  • Haskellはとても奇妙なように見えて学ぶのつらいけど、最初のハードルを超えたら後は楽です
  • Haskellを学ぶことは初めてプログラムについて学ぶことと似ています、楽しいよ!
  • Haskellによってあなたは異なった考え方をせざるを得なくなる

So what's Haskell?

Haskellは純粋関数型言語です。

  • 純粋関数型言語ではコンピュータに何をするか伝えない。その代わりコンピュータにそれが何なのかを伝える。
  • 純粋関数型言語ではある変数をsetした後、別のなにかに変更することはできないです。
  • [補足] "純粋な"関数型言語ではなく、"純粋関数"という概念がある。純粋関数は副作用を持たず、参照透過性を持つ

副作用

  • 純粋関数型において、関数には副作用がない。関数ができる唯一のことは何かを計算し結果を返すことのみ
  • [補足]例えば標準出力への文字出力も副作用である。Haskellではモナドを使って関数の純粋性を保ったままそのような作用を実行する

参照透過性

  • 関数が同じパラメータで2回呼ばれた場合、同じ結果が返されることを保証
  • コンパイラがプログラムの振る舞いを推論できるようにするだけでなく、関数が正しくそして単純な関数を結合することでより複雑な関数を作ることを簡単に人間が推論(そして証明さえも)できるようになる

命令型言語では一連のタスクを与え実行してもらうことで物事を成し遂げており、実行中は状態が変化可能である。

Haskellは怠け者です。

遅延評価

  • Haskellは結果を必要とされない限りは関数を実行しそして計算しようとはしない
  • 参照透過性により、プログラムをデータ変換の連続と考えることができる。このHaskellの挙動は参照透過性によりうまく動作する

遅延評価 - Wikipedia

  • [補足]実際には業務でHaskellを書く場合、遅延評価で面倒なことも多いため、デフォルトの評価戦略を正格評価にする言語拡張が最近のGHC(GHC8.0)に入った。

    さようなら遅延評価 - あどけない話

Haskellは静的型付けです。

  • コンパイル時にエラーの可能性がある部分をとらえることができる
  • Haskellには 型推論 がある

Haskellはエレガントで簡潔です。

  • 命令型プログラミング言語と同等のものを短く書くことができる

Haskellはめっちゃ頭のいい人によって作られました。

What you need to dive in

  • テキストエディタとHaskellコンパイラが必要です。
  • GHCと呼ばれるもっとも広く使われているHaskellコンパイラを使っていきます。
  • [補足]GHCはGlasgow Haskell Compilerの略。グラスゴー大学のKevin Hammondが開発を始めたため。

GHC

  • Haskell script(.hsのファイル)をコンパイルできます
  • ghciというインタラクティブモードも用意されています

MacでのHaskell環境の構築 - Qiita

2. Starting Out

Starting Out

Ready, set, go!

簡単な計算

In [1]:
2 + 15
17
In [2]:
49 * 100
4900
In [3]:
1892 - 1472
420
In [4]:
5 / 2
2.5

()で優先順位を明確にすることができます

In [3]:
(50 * 100) - 4999
50 * 100 - 4999
50 * (100 - 4999)
1
1
-244950

負数を扱う時は ()でくくらないとGHCIに怒られます

In [15]:
5 * (-3)
-15
In [19]:
5 * -3
<interactive>:1:1: error: Precedence parsing error cannot mix ‘*’ [infixl 7] and prefix `-' [infixl 6] in the same infix expression
In [2]:
-- これは通る。なぜなのか?
-5 * 3
-15

論理演算子

  • boolean関連のoperator and: &&, or: ||, not: not
In [8]:
True && False
Evaluate
Found:
True && False
Why Not:
False
False
In [9]:
True && True
Evaluate
Found:
True && True
Why Not:
True
True
In [10]:
False || True
Evaluate
Found:
False || True
Why Not:
True
True
In [12]:
not False
Evaluate
Found:
not False
Why Not:
True
True
In [21]:
5 == 5
True
In [22]:
1 == 0
False

/=はnot equal、 x /= y = not (x == y)

In [23]:
5 /= 5
False
In [24]:
5 /= 4
True
In [4]:
"hello" == "hello"
-- `''`は1文字のcharacter、 `""`は複数文字(書いていないけど)
True

同じ型じゃないと +とか ==したときに怒られちゃうよ

- ちなみに整数は卑怯なので浮動小数点として振る舞える
In [6]:
5 == True
<interactive>:1:1: error:
• No instance for (Num Bool) arising from the literal ‘5’
• In the first argument of ‘(==)’, namely ‘5’
In the expression: 5 == True
In an equation for ‘it’: it = 5 == True
In [7]:
5 + 4.0
9.0

関数

  • Haskellでは以下のように関数を呼び出す
    • パラメータを ()の中で記述する必要はなく、スペースを挿入する
    • 複数のパラメータがあった際、 ,で区切らずスペースで区切る
  • 関数の実行が一番優先度が高い
  • 関数が2つの引数を取る場合、バッククオートを用いて infix functionとして呼ぶことができる
  • bar (bar 3)はCでいうところの bar(bar(3))
In [27]:
succ 8
9

参考:

succ(successor functionについて)

後者関数 - Wikipedia

原始再帰関数 - Wikipedia

再帰理論 - Wikipedia

  • [補足]Haskellで関数のヘルプを見たり、関数を探したい場合どうするか

    Hoogleで検索する。Haskellerはよく関数の型でふんわり欲しい関数を検索するらしい

    Hoogle

    検索結果からはHackageに跳んで詳細が観れる。(Pythonで言う所のPyPI)

In [28]:
min 9 10
9
In [29]:
min 3.4 3.2
3.2
In [30]:
max 100 101
101
In [31]:
succ 9 + max 5 4 + 1
16
In [32]:
(succ 9) + (max 5 4) + 1
Redundant bracket
Found:
(succ 9) + (max 5 4)
Why Not:
succ 9 + (max 5 4)
Redundant bracket
Found:
(succ 9) + (max 5 4)
Why Not:
(succ 9) + max 5 4
16
In [34]:
div 92 10
9
In [35]:
92 `div` 10
9

Baby's first functions

  • 関数定義: 関数名 引数 = 処理
  • Haskellは関数定義の記述順序は関係ない
In [36]:
doubleMe x = x + x
In [37]:
doubleMe 9
18
In [38]:
doubleMe 8.3
16.6
In [39]:
doubleUs x y = x*2 + y*2
In [40]:
doubleUs 4 9
26
In [41]:
doubleUs 2.3 34.2
73.0
In [43]:
doubleUs 28 88 + doubleMe 123
478
In [44]:
doubleUs x y = doubleMe x + doubleMe y

if式

  • elseの記述が義務付けられている
  • Haskellでは全てのexpression(式)や関数は必ず何かを返す必要がある
    • if文はexpression
    • 5は5を返すexpression
    • 4+8はexpression
    • x+yはexpression
In [45]:
doubleSmallNumber x = if x > 100  
                        then x  
                        else x*2
In [47]:
doubleSmallNumber 101
doubleSmallNumber 100
101
200

関数名につく「'」

  • Haskellのsyntaxでは特別な意味をもっていないので、関数名に使える
  • 関数名の最後に「'」を付与するときは以下のどれか
    1. 関数がstrict(正格) version(lazyでない)ことを意味している
    2. 「'」がついていない関数 or 変数の少し変更されたバージョンである
In [48]:
doubleSmallNumber' x = (if x > 100 then x else x*2) + 1
In [49]:
doubleSmallNumber' 101
doubleSmallNumber' 100
102
201

命名規則

  • 先頭は小文字
  • 変数がない関数のことをdefinition もしくは nameと呼ぶ。
In [ ]: