map関数

# map関数

## 初めに
+ Haskellを学ぶ際には、map関数を避けて通れない、ということで、自分自身混乱しかけたので、まとめてみました。
+ 値と関数を同一視すること。そのためには、型を意識することが大事です。


## 準備

>> https://ja.wikipedia.org/wiki/Haskell

> 変数に束縛するのが定数であるか関数であるかにかかわらず、「変数 = 値」という一貫した形でも定義できる。


ということで、関数も値も変数と呼ぶ。

関数型

```hs
--関数も変数
--[引数の型(型変数)] -> [返り値の型]の形。

--1変数引数の場合
Prelude> :t fst
fst :: (a, b) -> a
                        {-
 ↑      ↑　 
変数   型変数　
-}

Prelude> :t head
head :: [a] -> a
                        {-
 ↑      　↑　 
変数   　型変数　
-}
Prelude> :t tail
tail :: [a] -> [a]
                        {-
 ↑      ↑　 
変数   型変数　
-}
```

+ 1変数関数の場合

```hs
Prelude> head [1,2,3,4]
1
Prelude> :t head
head :: [a] -> a
```

head関数を2つの側面から見る。(なので、関数も変数は見方が違うだけのもの)
　1. リストを引数にとり、戻り値を返す関数
　2. [a] -> a型の変数

多変数関数の場合を考えると、より鮮明になる。


+ 2変数関数の場合

```hs
--takeはIntとリストを引数に取り、先頭から指定された数の要素を取り出すリストを返す2変数関数。
Prelude> take 1 [1,2,3]
[1]

Prelude> :t take
take :: Int -> [a] -> [a]
{-
take :: Int -> ([a] -> [a]) のこと。
-}
```

take関数を3つの側面から見ることができる。(なので、関数も変数は見方が違うだけのもの)
　1. Int と [a]を引数にとり、[a]を返す関数
　2. Intを引数に取り、[a] -> [a]型の変数を返す関数
　3. Int -> [a] -> [a]型の変数

2番目のとらえ方を採用すると、(take 1)関数は、
　1. [a]を引数に取り、[a]を返す関数
　2. [a] -> [a] 型の変数

の二つの見方ができる。

```hs
Prelude> :t take 1
take 1 :: [a] -> [a]
```

## map関数について
### 定義
map関数は、1変数関数と、リストを受け取り、その関数をリスト内のすべての要素に対して、作用させて、新規のリストを戻り値とする。

### 例  [^1]

[^1]: Haskellの内包表記でも書けますが、今回はmap関数を説明するために簡単な例を用いています。

```hs
Prelude> map (+2) [2,3,4,5,6]
[4,5,6,7,8]
```
というような使用例。 

C#を知っているなら、LINQのSelect関数と同じ。

```csharp
using System.Linq;

public class Hello{
    public static void Main(){
        
        //SelectがHaskellのmap関数に相当。
        Enumerable.Range(2,5).Select(c =>c + 2)
        .ToList()
        .ForEach(c=>System.Console.WriteLine(c));
        
    }
}
```

もしくは、pythonのリスト内包表記と同等。

```py3
print ([x+2 for x in range(2,7)])
```

### 説明

```hs
Prelude> :t map
map :: (a -> b) -> [a] -> [b]
```

map関数は3つの側面から見ることができる。
　1. (a -> b)型の変数 と [a]を引数にとり、[b]を返す関数
　2. (a -> b)型の変数を引数に取り、[a] -> [b]型の変数を返す関数
　3. (a -> b) -> [a] -> [b]型の変数

2番目の考え方が特に大事。

冗長だが、2項演算子(+)を用いるので、同様の説明をする。

```hs
Prelude> :t (+)
(+) :: Num a => a -> a -> a
```

+演算子は3つの側面から見ることができる。
　1. a と aを引数にとり、aを返す関数
　2. a型の変数を引数に取り、 a -> a型の変数を返す関数
　3. a -> a -> a型の変数

2番目の観点で+演算子を見ると、

```hs
Prelude> :t (+2)
(+2) :: Num a => a -> a
```

ということで、(+2)をa -> a型の変数とみることができる。

map関数の挙動としては、

```hs
Prelude> map (+2) [2,3,4,5,6]
[4,5,6,7,8]
-- a -> a型の変数である(+2)とリストを引数に取っている
-- !! 1 は、リストから、1番目の要素を取ってくる演算子
Prelude> map (+2) [2,3,4,5,6] !! 1
5
```

## map関数の応用
第一引数に、2変数関数を持ってきたときはどうなるのか？

```hs
f :: a -> b -> c
```

これは、a を引数として、b -> c型の変数を返す関数とみることもできる。
map (+) [2,3,4,5,6] !! 1は、(+3)、つまり、1変数関数となる。

(+3)自体はコンソールにprintできないので、以下を実行してみる。

```hs
--  map (+) [2,3,4,5,6] !! 1は、a -> a型の引数(1変数関数)
Prelude> :t (map (+) [2,3,4,5,6] !! 1)

--map関数にa -> a型の変数(+3) と[a]を引数に取る。
(map (+) [2,3,4,5,6] !! 1) :: Num a => a -> a
Prelude> map (map (+) [2,3,4,5,6] !! 1) [2,3,4,5,6]
[5,6,7,8,9]
 ```

ということで、問題ない。


## ラムダ式

ラムダ式も、関数と変数を同一視すれば理解は容易い。

```hs
-- (\x -> x + 3)は、　a->a型の変数
Prelude> :t \x -> x + 3
\x -> x + 3 :: Num a => a -> a
--map関数にa -> a型の変数(\x -> x + 3) と[a]を引数に取る。
Prelude> map (\x -> x + 3) [2,3,4,5,6]
[5,6,7,8,9]
```


## 次やること
次はfmapをまとめたい。

## 参考
すごいHaskellたのしく学ぼう!
https://www.amazon.co.jp/%E3%81%99%E3%81%94%E3%81%84Haskell%E3%81%9F%E3%81%AE%E3%81%97%E3%81%8F%E5%AD%A6%E3%81%BC%E3%81%86-Miran-Lipova%C4%8Da/dp/4274068854