すごいHaskellたのしく学ぼう！ 第1章  読書メモ


##対話型インタープリタの起動

```sh
ghci
```

インタープリタの設定をするにはホームディレクトリに``.ghci``という名前のファイルを作成し、あれやこれやと記述する。
例えばプロンプトを変更するには下記のように記述する。

```.ghci
:set prompt "ghci> "
```

##演算子

たいていの演算子は一般的な言語と同じだが、ノットイコールは``!=``ではなく``/=``なので要注意。

##関数の呼び出し

```haskell
hoge 1 10
```

- 引数を囲むカッコは不要
- 引数の区切りはスペース

##バッククォート

関数をバッククォートで囲むと中置関数と呼び出せるようになる。

```haskell
div 10 2
10 `div` 2
```

##関数をインタープリタにロードする

``:l``ファイル名でロードできる。この際、拡張子は不要。

```
:l hoge
```

##関数の定義順

順番に定義する必要はない。

##if文

必ず``else``が必要。
Haskellの``if``は必ず値を返す式であって文ではない。

```haskell
douleSmallNumber x = if x > 100
  then x
  else x * 2
```

##アポストロフィ

Haskellにおいてアポストロフィは特別な意味を持たない。関数に利用可能な文字。
慣習的に正格(遅延じゃない)版の関数を表したり、少し変更したバージョンの関数に似た名前を付けるために使用する。

```haskell
douleSmallNumber' x = if x > 100
  then x
  else x * 2
```

```haskell
douleSmallNumber'Hoge x = if x > 100
  then x
  else x * 2
```

##関数名

小文字始まり。大文字区切り。

##let

GHCi内で名前を定義する際に使用。

```hakell
let hoge = 123
```

##リスト

###リストの定義

```haskell
let hoge = [1,2,3]
```

###リストの連結

``++``演算子を用いる。

```haskell
[1, 2] ++ [4, 5]
```

###リストに``++``する際の注意点

左のリストの最後まで走査するので要素数が多い場合は動作が遅くなる恐れがある。

###リストの先頭に要素を追加する

``:``演算子を用いる。``:``演算子は``cons``演算子とも呼ばれる。

```haskell
'H':"Hoge"
1:[2,3,4,5]
```

``:``演算子の第1引数は追加するリストと同じ型の単一要素。
``++``は両方ともリスト。

###要素へのアクセス

``!!``演算子を用いる。

```haskell
[1,2,3] !! 0
"Hoge" !! 1
```

###リスト内のリスト

```haskell
[[0,1], [2,3]]
```

それぞれの長さは自由だが、要素の型は同じでないいけない。

###リストの比較

```haskell
[1,2,3] < [1,2,4]
-- True
[3,2] > [2,5]
-- True
[] < [1]
-- True
```

先頭から順に比較していく。同じ場合は次の要素。
また空ではないリストは空のリストよりも常に大きい

###リスト操作いろいろ

```haskell
-- 先頭を取得
head [1,2,3]

-- 先頭を取り除いた要素を取得
tail [1,2,3]

-- 末尾の要素を取得
last [1,2,3]

-- 末尾の要素を除いた要素を取得
init [1,2,3]

-- リストの長さを取得
length [1,2,3]

-- リストが空かを取得
null []

-- リストを逆順
reverse [1,2,3]

-- リストの要素を指定された数だけ取得
-- 第1引数がリストの要素数より大きい場合はリスト全体を返す
-- ゼロを指定すると[]を返す
take 2 [1,2,3]

-- 指定された数だけ要素を削除したリストをす返す
drop 2 [1,2,3]

-- 最も大きい要素を返す
maximum [1,2,3]

-- 最も小さい要素を返す
minimum [1,2,3]

-- 要素の和を返す
sum [1,2,3]

-- 要素の積を返す
product [1,2,3,4]

-- 指定された値を含むかを返す
-- 中置関数だと読みやすい
elem 4 [1,2,3,4]
4 `elem` [1,2,3,4]
```

##レンジ(range)

列挙可能な要素を持つリストを作る。

```haskell
[1..10]
-- [1,2,3,4,5,6,7,8,9,10]
```

ステップを指定することもできる。

```haskell
[2,4..20]
--[2,4,6,8,10,12,14,16,18,20]
```

減少する場合は下記のようにする。

```haskell
[20,19..1]
```

上限を無限とすることもできる。

```haskell
take 5 [13,26..]
```

###無限リストの生成

``cycle``は受け取った要素を無限に繰り返す。

```haskell
take 10 (cycle[1,2,3])
-- [1,2,3,1,2,3,1,2,3,1]
```

``repeat``は指定された要素を無限に繰り返す。

```haskell
take 10 (repeat 5)
```

``replicate``は長さと要素を受け取り、指定された長さのリストを返す。

```hakell
replicate 3 10
-- [10,10,10]
```

##リスト内包表記

```haskell
[x*2 | x <- [1..10]]
-- [1,2,3,1,2,3,1,2,3,1]
```

1. ``[1..10]``のリストの1つずつ取り出し``x``に設定(束縛)
2. ``x``に2をかける

条件(述語)を付け加えフィルタすることもできる。

```hakell
[x*2 | x <- [1..10], x*2 >= 12]
-- [12,14,16,18,20]
```

述語は複数可。

```haskell
[x | x <- [10..20], x /= 13, x /= 15]
-- [10,11,12,14,16,17,18,19,20]
```

複数のリストを使うことも可能。

```haskell
[x+y | x <- [1,2,3], y <- [10,20,30]]
-- [11,21,31,12,22,32,13,23,33]
```

##タプル

タプルは複数の違う型の要素を格納して1つの値にすることができる。
リストとは違いサイズ固定。

```haskell
(1,3)
-- (1,3)
*Main> (1, 2,"aBCdE")
-- (1,2,"aBCdE")
```

###タプルの型

要素数が異なると別の型。


```haskell
[(1,2), (3,4,5), (6,7)]

-- <interactive>:72:9:
--     Couldn't match expected type `(t0, t1)'
--                 with actual type `(t2, t3, t4)'
--     In the expression: (3, 4, 5)
--     In the expression: [(1, 2), (3, 4, 5), (6, 7)]
--     In an equation for `it': it = [(1, 2), (3, 4, 5), (6, 7)]
```

###ペアを使う

```haskell
fst (1,2)
-- 1
snd (3,4)
-- 4
```

###zip関数

```haskell
zip [1,2,3] ["hoge","fuga","hige"]
-- [(1,"hoge"),(2,"fuga"),(3,"hige")]
```

###直角三角形を見つける

- 3辺の長さは全て整数
- 各辺の長さは10以下
- 周囲の長さは24に等しい

```hakell
triples =
    [
        (a,b,c) | c <- [1..20], a <- [1..c], b <- [1..a],
        a^2 + b^2 == c^2, a+b+c == 24
    ]
-- [(8,6,10)]
```

最初に解となる集合を生成し、それから解に辿り着くまでの変換、フィルタリングを行う手法は関数プログラミングではよくある手法。