イマドキな Haskell で書かないもの: return, >>, forM_, mzero, mplus, `shiftL`, その他

# 0. まとめ

`liftA2` 関数および `liftA3` 関数以外の持ち上げ関数は計算コストが高い可能性があるため、`liftA2` 関数および `liftA3` 関数や演算子 `<$>` および演算子 `<*>` を使用します:

- `liftA`
- `liftM`, `liftM2`, `liftM3`, `liftM4`, `liftM5`
- `ap`

`Applicative` クラスと `Monad` クラスで同じ機能が提供されている場合、`Monad` クラスでなく `Applicative` クラスを使用します:

- 基本
    - `return = pure`
    - `(>>) = (*>)`
    - `mzero = empty`
    - `mplus = (<|>)`
- ループ
    - `mapM_ = traverse_`, `forM_ = for_`
    - `sequence_ = sequenceA_`
- リストのような関数
    - `mapM = traverse`、`forM = for`
    - `sequence = sequenceA`
    - `msum = asum`

可能であれば型クラス制約 `MonadPlus m` でなく以下のものを使用します:

- `Alternarive m`
- `Monad m`
- `Alternarive m, Monad m`

ビット演算に関して、演算子が提供されている場合は関数の中置記法でなく演算子を使用します:

- `(.^.) = xor`
- `(.<<.) = shiftL`, `(!<<.) = unsafeShiftL`
- `(.>>.) = shiftR`, `(!>>.) = unsafeShiftR`

# 1. 持ち上げ関数

`liftA2` 関数は元はメソッドでありませんでしたが、現在は `Applicative` クラスのメソッドになっています。

`liftA2` 関数や演算子 `<*>` はメソッドのため、具体的な型ごとに最適な計算をするはずです。

演算子 `<$>` は `(<$>) = fmap` と定義されていて、`fmap`  関数は `Functor` クラスのメソッドのため、最適な計算をするはずです。

`liftA3` 関数は `liftA2` 関数と演算子 `<*>` を用いて定義されているため、(他にその型専用の関数がなければ) 最適な計算を期待できます。

`liftA2` 関数および `liftA3` 関数以外の持ち上げ関数は最適な計算をするとは限らないため、使用しない方が良いです。

```haskell:悪い
liftA f x
liftM f x
f `liftA` x
f `liftM` x

liftM2 f x y

liftM3 f x y z

pure f `ap` x1 `ap` x2 `ap` x3 `ap` x4 `ap` x5 `ap` x6
```

```haskell:良い
f <$> x

liftA2 f x y

liftA3 f x y z
liftA2 f x y <*> z

liftA2 f x1 x2 <*> x3 <*> x4 <*> x5 <*> x6
liftA3 f x1 x2 x3 <*> x4 <*> x5 <*> x6
```

参考「[[Haskell] モナド 演算子 まとめ - Qiita](https://qiita.com/kerupani129/items/333155e5e2dee644d6dc)」
参考「[[Haskell] f <$> x <*> y よりも liftA2 f x y の方が計算コストを抑えられることがある - Qiita](https://qiita.com/kerupani129/items/c94f389c68a45f1e64d3)」

参考「[(<$>) - Data.Functor](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Functor.html#v:-60--36--62-)」
参考「[(<*>) - Control.Applicative](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Applicative.html#v:-60--42--62-)」
参考「[liftA2 - Control.Applicative](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Applicative.html#v:liftA2)」
参考「[liftA3 - Control.Applicative](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Applicative.html#v:liftA3)」

# 2. `Applicative` クラスと `Monad` クラス

`Monad` クラスは元々 `Applicative` クラスのサブクラスでありませんでしたが、現在はサブクラスになっています。

そのため、`Monad` クラスと `Applicative` クラスで同じ機能が提供されていることがあります。

もし初めから `Monad` クラスが `Applicative` クラスのサブクラスであれば `Monad` クラスでは提供されなかったはずの機能のため、`Applicative` クラスを使用します。

## 2.1. 基本

```haskell:悪い
return x

x >> y

mzero

mplus x y
x `mplus` y
```

```haskell:良い
pure x

x *> y

empty

x <|> y
```

※ちなみに `mempty` 関数および `mconcat` 関数は `MonadPlus` クラスのメソッドでなく `Monoid` クラスのメソッドであり、ここでは関係ありません。

参考「[[Haskell] モナド 演算子 まとめ - Qiita](https://qiita.com/kerupani129/items/333155e5e2dee644d6dc)」
参考「[[Haskell] モナドの計算を中断する - Qiita](https://qiita.com/kerupani129/items/f6819466b49fe799b40c)」

参考「[pure - Control.Applicative](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Applicative.html#v:pure)」
参考「[(*>) - Control.Applicative](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Applicative.html#v:-42--62-)」
参考「[empty - Control.Applicative](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Applicative.html#v:empty)」
参考「[(<|>) - Control.Applicative](https://hoogle.haskell.org/?scope=set%3Aincluded-with-ghc&hoogle=(%3C%7C%3E))」

## 2.2. ループ

```haskell:悪い
mapM_ f xs
forM_ xs f

sequence_ xs
```

```haskell:良い
traverse_ f xs
for_ xs f

sequenceA_ xs
```

参考「[[Haskell] IO () 型の for ループ - Qiita](https://qiita.com/kerupani129/items/1521534e46750799d5de)」

参考「[traverse_ - Data.Foldable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Foldable.html#v:traverse_)」
参考「[for_ - Data.Foldable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Foldable.html#v:for_)」
参考「[sequenceA_ - Data.Foldable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Foldable.html#v:sequenceA_)」

## 2.3. リストのような関数

```haskell:悪い
mapM f xs
forM xs f

sequence xs

msum xs
```

```haskell:良い
traverse f xs
for xs f

sequenceA xs

asum xs
```

参考「[traverse - Data.Traversable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Traversable.html#v:traverse)」
参考「[for - Data.Traversable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Traversable.html#v:for)」
参考「[sequenceA - Data.Traversable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Traversable.html#v:sequenceA)」
参考「[asum - Data.Foldable](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Foldable.html#v:asum)」

## 2.4. `MonadPlus` クラス

型クラス制約 `MonadPlus m` は可能であれば `Alternative m` と `Monad m` に分けます。

例として、`mfilter` 関数の型クラス制約 `MonadPlus m` を書き換えると以下のようになります。

※説明のためソースコードを一部改変。

```haskell:悪い
mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
mfilter p mx = do
    x <- mx
    if p x
        then return x
        else mzero
```

```haskell:良い
mfilter' :: (Alternative m, Monad m) => (a -> Bool) -> m a -> m a
mfilter' p mx = do
    x <- mx
    if p x
        then pure x
        else empty
```

※ちなみに `return x` や `pure x` を `mx` としてしまうと型によっては動作が変わるため、`mx` には書き換えられません。

参考「[mfilter - Control.Monad](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Monad.html#v:mfilter)」

# 3. ビット演算

一部のビット演算に関して、ビット演算子が追加されています。

```haskell:悪い
x `xor` y

x `shiftL` i
x `unsafeShiftL` i

x `shiftR` i
x `unsafeShiftR` i
```

```haskell:良い
x .^. y

x .<<. i
x !<<. i

x .>>. i
x !>>. i
```

参考「[(.^.) - Data.Bits](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Bits.html#v:.-94-.)」
参考「[(.<<.) - Data.Bits](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Bits.html#v:.-60--60-.)」
参考「[(!<<.) - Data.Bits](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Bits.html#v:-33--60--60-.)」
参考「[(.>>.) - Data.Bits](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Bits.html#v:.-62--62-.)」
参考「[(!>>.) - Data.Bits](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Bits.html#v:-33--62--62-.)」