Data.Monoid.First と Data.Semigroup.First あるいは Last
Data.Monoid.First
のドキュメントを見ていたら次の記述を見つけたことから始まる記事です。
This type will be marked deprecated in GHC 8.8, and removed in GHC 8.10. Users are advised to use the variant from Data.Semigroup and wrap it in Maybe.
すでに GHC 8.10 がリリースされているのにまだなくなっていない気がしますが(GHC 9.0.1-alpha1 にもまだある)、Data.Monoid.First
よりも Data.Semigroup.First
を使うべきなようです。
以降、次のようにモジュールを参照します。
> import qualified Data.Semigroup as S > import qualified Data.Monoid as M
復習
セミグループの復習として、文字列とその結合を見ると次のような挙動をします。
> "a" <> "bc" "abc" > "" <> "abc" "abc"
モノイドの単位元は ""
です。
> mempty <> "abc" "abc"
Data.Semigroup.First
さてここにセミグループのインスタンスでない型 Char
があります。
> 'a' <> 'b' <interactive>:13:1: error: • No instance for (Semigroup Char) arising from a use of ‘<>’ • In the expression: 'a' <> 'b' In an equation for ‘it’: it = 'a' <> 'b'
Data.Semigroup.First
にくるめばセミグループになります。
> S.First 'a' <> S.First 'b' First {getFirst = 'a'}
左が返り値となります。
Data.Monoid.First
では Data.Monoid.First
で Char
をくるめるでしょうか?
> M.First 'a' <interactive>:16:9: error: • Couldn't match expected type ‘Maybe a’ with actual type ‘Char’ • In the first argument of ‘M.First’, namely ‘'a'’ In the expression: M.First 'a' In an equation for ‘it’: it = M.First 'a' • Relevant bindings include it :: M.First a (bound at <interactive>:16:1)
Data.Monoid.First
でくるめるのは Maybe a
だけです。
> M.First $ Just 'a' First {getFirst = Just 'a'}
Just
同士の演算は Data.Semigroup.First
と同じです。
> M.First (Just 'a') <> M.First (Just 'b') First {getFirst = Just 'a'}
Nothing
がからむと Nothing
でない最初の要素が返ります。
> M.First Nothing <> M.First (Just 'a') <> M.First (Just 'b') First {getFirst = Just 'a'}
Data.Maybe
Data.Maybe
はモノイドとしては次のような挙動が採用されています(雑になってきた)。
> Nothing <> Nothing Nothing > Nothing <> Just "a" Just "a" > Just "a" <> Nothing Just "a" > Just "a" <> Just "b" Just "ab"
Maybe a
の a
はモノイドである必要があります。
もういちど Data.Semigroup.First
最初の引用を再掲します。
This type will be marked deprecated in GHC 8.8, and removed in GHC 8.10. Users are advised to use the variant from Data.Semigroup and wrap it in Maybe.
というわけで Data.Monoid.First
の代わりに Data.Semigroup.First
を使うように置き換えてみます。
元々の Data.Monoid.First
を次に再掲します。
> M.First Nothing <> M.First (Just 'a') <> M.First (Just 'b') First {getFirst = Just 'a'}
なんか M.First Nothing
が無視されるのはただの Nothing
っぽいので Maybe ?
という形になりそうです(ほんまか?)。
Maybe ?
の演算は ?
の演算をして Just
にくるむので ?
は左を選ぶやつにすればいいようです。
Data.Semigroup.First
がそれなので、M.First a ≡ Maybe (S.First a)
になりそうです。
……というのがドキュメントに書いてました。
Note the following equivalence:
Data.Monoid.First x === Maybe (Data.Semigroup.First x)