Functor 整理

## 基本用語

#### data宣言 -- 値コンストラクタ
```haskell
-- data 型名 = 値コンストラクタ
data Bool = False | True
```
型名は型の名称を、値コンストラクタはデータ型が取りうる値を表す。
<br>

```haskell
-- 値コンストラクタは名称をつけることができる
data Shape = Circle Float Float Float | 
                Rect Float Float Float Float 
```
CircleはFloat型引数を三つとる値（コンストラクタ）である。 
※「Circleというデータ型を定義している」のではなく「Circleという名称の値を宣言している」というイメージ。
Shape型の取りうる値はCircleとRectの2種類。
<br>
```
ghci> :t Circle  // 宣言前
<interactive>:1:1: error: Data constructor not in scope: Circle
ghci> data Shape = Circle Float Float Float // 宣言
ghci> :t Circle // ghciに認識される
Circle :: Float -> Float -> Float -> Shape
```
Circleのその実は、ただの関数であるともいえる。
<br>
```haskell
data Shape = Circle { x ::Float, y:: Float, r:: Float } | 
Rect {left::Float , top::Float, right::Float, bottom::Float}
```
レコード構文という上記書き方で引数にラベル付が可能
<br>
```haskell
-- 面積を求める関数
area :: Shape -> Float
area (Circle _ _ r) = pi * r^2
area (Rext x1 y1 x2 y2) = (abs $ x2-x1) * (abs $ y2-y1)

---
ghci> area $ Rect 0 0 10 10
100

-- Circleは値なので以下の書き方はできない
area :: Circle -> Float
area (Circle _ _ r) = pi * r^2
```
関数を作成

#### data宣言 -- 型コンストラクタ
```haskell
-- data 型コンストラクタ 型引数 = 値コンストラクタ
data Maybe a = Nothing | Just a
```
型コンストラクタは型を引数にとって新しい型を生み出す。
Maybeは型コンストラクタといい、aという型（引数）から新しい型を生み出す。

```haskell
ghci> :t Nothing
Nothing :: Maybe a
ghci> :t Just "hoge"
Just "hoge" :: Maybe String -- Maybe String　型
ghci> :t Just 1
Just 1 :: Num a => Maybe a -- 型推論
```
Maybeは型を生み出す型コンストラクタであるため、単独では値になれない。

型引数がない型（IntやBool）、型引数があるが全て埋まっている型（Maybe String）型 を具体型という。
<br>
```haskell
-- この関数はNothingを引数に取れる
fn :: Maybe Int -> Int
```
Nothing :: Maybe a は多相的、つまりa型がなんであれ、Maybe型コンストラクタを持つすべての型にはNothingを入れられる。

この仕組みを使って、Maybeという値を持つ（Just a) か持たないか（Nothing）を表す値といった抽象な概念を表現している。
<br>
```haskell
-- ベクトル加算を表現
data Vector a = Vector a a a deriving (Show)

vplus:: (Num a) => Vector a -> Vector a -> Vector a
vplus (Vector x y z) (Vector i j k) = Vector (x+i) (y+j) (z+k)

main = do
    print $ vplus (Vector 3 5 8) (Vector 9 2 8)
```


#### 型クラス

```haskell
class Foo a where
    foo :: a -> String
instance Foo Bool where
    foo True :i = "True"
    foo False = "False"
instance Foo Int where
    foo x = show x
main = do
    print $ foo True -- "True"
    print $ foo False -- "False"
    print $ foo (2 ::Int) -- "2"
```
classは特定の振る舞いを表す。同じ振る舞いをする型たちに共通のインターフェースを提供する。
新たな型クラスを定義するのがclass、型を型クラスのインスタンスにするのがinstance


#### 種類

```haskell
ghci> :i Int
type Int :: *
```
```haskell
ghci> :i Maybe
type Maybe :: * -> *
data Maybe a = Nothing | Just a
```
型にはラベルがある。型の型なんて言ったりもする。
「*」が具体型を表している。
上記Maybeは「一つの具体型を受け取って具体型となる」と読み、型コンストラクタであることを示している。

## Fanctor

```haskell
ghci> :i Functor 
type Functor :: (* -> *) -> Constraint
class Functor f where
  fmap :: (a -> b) -> f a -> f b
```
type より　型コンストラクタから型制約ありの型（※1）を返すことがわかるので、fはなんらかの型コンストラクタである読める。
fmapは 「a->b　の関数」と「型コンストラクタfに型引数aを適応した型」を受け取り、「型コンストラクタfに型引数bを適応した型」を返すと読む。
混同するかもだが、f関数にaを適応すると言った意味ではなく、「f a」 で一つの具体型を表す。
<br>
```haskell
instance Functor Maybe where
    fmap _ Nothing = Nothing
    fmap f (Just a) = Just (f a)
```
型コンストラクタを伴う具象型はFunctorになり得る(*2)。Maybe型コンストラクタはFunctorのインスタンスである。
Maybeの中身がNothingならNothingを返し、なんらかの値をもったMaybeであれば,第一引数のfをaに適応する。
同じ単語がでてくるのでややこいが、ここでは
`fmap f (Just a) = Just (f a)` のf は (a -> b)の関数のことであり、aは(Just a)の中身の値aである。 Functor型クラスのf,aとは異なるので注意。
<br>

```haskell
ghci> fmap (*3) (Just 11) -- 値があれば関数を適応する
Just 33
ghci> fmap (*3) Nothing -- なにもなければ何もないを返す
Nothing
```
Just 11のような「型コンストラクタで意味付けされたなんらかの値」の中身11に関数*3を適応して、「同じく型コンストラクタで意味付されたなんらかの値」 Just 33 を返す。
「型コンストラクタで意味付けされたなんらかの値」のことを文脈といったりする。fmapは文脈を変えずに中身の値だけ変える道具」といったイメージ。
<br>
```
instance Functor (Either a) -- Defined in ‘Data.Either’
instance Functor [] -- Defined in ‘GHC.Base’
instance Functor Solo -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Functor IO -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Functor ((,,,) a b c) -- Defined in ‘GHC.Base’
instance Functor ((,,) a b) -- Defined in ‘GHC.Base’
instance Functor ((,) a) -- Defined in ‘GHC.Base’
```
Functorのinstanceは上記、一般的には「全体を写せるもの」は全部Functor なんていったりする。
Maybeの例でも,Maybeの文脈はそこねず、aをbに写したものと考えることができる。

<br>

#### Functorの説明表現
- なんらかの値を写せるもの
- 値を入れるなんらかのコンテナのような構造を持つ型
- なんらかの型をラッピングした（包み込んだ）型を


※1 
```haskell
ghci> :t (==)
(==) :: Eq a => a -> a -> Bool
```
この記事ではあまり気にしなくて良いが、Haskellには型制約という機能がある。(==>）がそれで、型引数aはEq（等値性比較クラス）のサブクラスである必要があるといった制約を設けている。


※2
```
fmap id = id
fmap (f . g) == fmap f . fmap g
```
Fanctorである条件は上記Functor即を満たすものである必要がる。