RustでFunctor書いてみる

少し前にRustのnightlyにGATが入ったらしいので、[Functors, Applicatives, And Monads In Pictures](https://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html)のFunctorまでを、Rustで書いてみることにしました。

Rustは趣味でコードを書いている程度で、Haskellは一行も書いたことがありません。それに、モナドが何なのかもサッパリ分かりません。なので、この記事の内容は正しくないかもしれません。どうかご了承くださいますようお願い致します。

あと、今回使用したRustのバージョンは、「rustc 1.51.0-nightly (0b644e419 2020-12-26)」になります。

##参考資料
[Functors, Applicatives, And Monads In Pictures](https://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html)
[箱で考えるFunctor、ApplicativeそしてMonad](https://qiita.com/suin/items/0255f0637921dcdfe83b)
[Monads and GATs in nightly Rust](https://www.fpcomplete.com/blog/monads-gats-nightly-rust/)
[RustのHigher-Kinded type Trait](https://keens.github.io/blog/2016/02/28/rustnohigherkinded_type_trait/)

##Maybe

```Haskell:Haskell
data Maybe a = Nothing | Just a

```

Maybe データ型、 Just a と Nothing の状態を表す

```Rust:Rust
#[derive(Debug, PartialEq)]
enum Maybe<A> {
    Just(A),
    Nothing,
}
```
#Functor

```Haskell:Haskell
> fmap (+3) (Just 2)
Just 5

> fmap (+3) Nothing
Nothing
```

箱に入った値に関数を適応して、その結果を箱に入れて返すみたいな感じ

Just(2) -> (+3) -> Just(5)

とりあえず書いてみる

```Rust:Rust
impl<A> Maybe<A> {
    pub fn fmap<B, F: FnOnce(A) -> B>(self, f: F) -> Maybe<B> {
        match self {
            Maybe::Just(x) => Maybe::Just(f(x)),
            Maybe::Nothing => Maybe::Nothing,
        }
    }
}
```
テストしてみる

```Rust:#[test]
assert_eq!(Maybe::Just(2).fmap(|v| 3 + v), Maybe::Just(5));
assert_eq!(Maybe::Nothing.fmap(|v: i32| 3 + v), Maybe::Nothing);
```

これって Option

```Rust:#[test]
assert_eq!(Some(2).map(|v| 3 + v), Some(5));
assert_eq!(None.map(|v: i32| 3 + v), None);
```

Haskell の typeclass は、Rust の trait らしいので trait で書きなおす

```Haskell:Haskell
class Functor f where
    map :: (a -> b) -> f a -> f b
instance Functor Maybe where
    fmap func (Just val) = Just (func val)
    fmap func Nothing = Nothing
```

```Rust:Rust
trait Functor<A> {
    fn fmap<B, F: FnOnce(A) -> B>(self, f: F) -> Maybe<B>;
}

impl<A> Functor<A> for Maybe<A> {
    fn fmap<B, F: FnOnce(A) -> B>(self, f: F) -> Maybe<B> {
        match self {
            Maybe::Just(x) => Maybe::Just(f(x)),
            Maybe::Nothing => Maybe::Nothing,
        }
    }
}
```

あれ？書けた気がする？

##GAT

気を取り直して本題のGATで書いてみる

`#![feature(generic_associated_types)]`

を頭に追加して

```Rust:Rust
trait Functor {
    type Unwrapped;
    type Wrapped<B>: Functor;

    fn fmap<F, B>(self, f: F) -> Self::Wrapped<B>
    where
        F: FnOnce(Self::Unwrapped) -> B;
}

impl<A> Functor for Maybe<A> {
    type Unwrapped = A;
    type Wrapped<B> = Maybe<B>;

    fn fmap<F: FnOnce(A) -> B, B>(self, f: F) -> Maybe<B> {
        match self {
            Maybe::Just(x) => Maybe::Just(f(x)),
            Maybe::Nothing => Maybe::Nothing,
        }
    }
}
```

##HKT

実はGAT入る前から書けてた

RustにはHKTないけど、関連型を駆使して書けるらしい

```Rust:Rust
trait HKT<U> {
    type Unwrapped;
    type Wrapped;
}

trait Functor<U>: HKT<U> {
    fn fmap<F: FnOnce(Self::Unwrapped) -> U>(self, f: F) -> Self::Wrapped;
}

impl<A, U> HKT<U> for Maybe<A> {
    type Unwrapped = A;
    type Wrapped = Maybe<U>;
}

impl<A, U> Functor<U> for Maybe<A> {
    fn fmap<F: FnOnce(Self::Unwrapped) -> U>(self, f: F) -> Self::Wrapped {
        match self {
            Maybe::Just(x) => Maybe::Just(f(x)),
            Maybe::Nothing => Maybe::Nothing,
        }
    }
}
```

##まとめ

「`type Wrapped<B>: Functor;`」な部分がGAT(Generic Associated Types)なところ

それにしてもモナドが何なのかサッパリわからん