前提: 型クラス
型クラスの話をしています。型クラスは、ダックタイピングのすごく良いやつです(適当)(コメントで識者がツッコんでくれる)
型クラス(とその具体例であるインスタンス)にはいろいろあるけど、今回はValidatedとTraverseについて話しているよ
- 言語によって呼び名はいろいろあるけどここではScala(のCatsライブラリ)での呼び名で書いています
- ValidatedはApplicative、Functorのインスタンスだよ(ApplicativeとFunctorのインスタンスであることを強調してValidated applicative functorと呼ぶことがあるよ)
- Monadじゃないよ
- Monad版はEitherが相当するよ
- TraverseはFunctorにtraverseという操作を導入した型クラスだよ
- 例えばListはTraverseのインスタンスだよ
Validated
Validatedは成功した計算をまとめるか、エラーを累積してまとめるかの操作を行うことができるデータ型だよ
https://typelevel.org/cats/datatypes/validated.html
https://qiita.com/nozomitaguchi/items/66bbee966e59281a68e8
類似の概念にEitherがあるよ
Eitherはエラーが発生した時点で計算を打ち切ってすぐに返るけどValidatedは全てのエラーを集めて回ってくれるよ

一番身近でかつ知ってたら「これ無しにコード書くとか機械語でコード書くようなもんだろ」ってなるのに全然知られてない構造、たぶんValidated applicative functorが1位な気がする(知ってれば、バリデーションがしたくなったらまずこれなしには話が始まらないのに…となる)
2023-04-28 10:19:47
Validation型を教えてもらったときに、感動した覚えがあります。 twitter.com/hisaketM/statu…
2023-04-28 17:32:53
少なくとも自分が係わった殆どのプロジェクトでValidationエラーを可能な限り集約して返す要件は存在していて、Validatedみたいなデータ構造は本当に必須と感じている
2023-04-28 18:25:42
ValidatedとNonEmptyListの合わせ技は必須だなぁと感じること多い。 kotlinというかarrowだとValidatedとEitherとの差がほぼなくてdeprecatedになっちゃったけど。 twitter.com/gakuzzzz/statu…
2023-04-28 20:27:08Applicative
ValidatedはApplicativeのインスタンスだよ
Applicativeは関数を適用すること、または2つの値の合成を一般化して、さらに拡張した振舞い(例: 関数と引数の両方が失敗するおそれがある)を導入できるようにした仕組みだよ
ApplivativeはFunctorに2つの操作、apとpureを導入した型クラスだけど、apをmap2で代用することもできるよ(相互に定義可能)
https://typelevel.org/cats/typeclasses/applicative.html
ちなみに、Functorは変換を一般化して、さらに拡張した振舞い(例: リストの全ての要素を変換する)を導入できるようにした仕組みだよ
おまけ: Monad は 逐次処理 を一般化して、さらに拡張した振舞い(例: 逐次処理が非同期処理で行われる)を導入できるようにした仕組みだよ

@yaito3014 applicative は map2<A,B,C>(fa: F<A>, fb: F<B>)(abToc: (A, B) -> C): F<C> ができるやつで、 例えば 「標準的な」Result モナドに関しては match fa { case Err(e) -> Err(e), case Ok(a) -> match fb { case Err(e) -> Err(e) case Ok(b) -> Ok(f(a,b)) } } ができます
2023-04-28 18:16:04注: ResultモナドというのはRustの文脈

モナドの有用な例は?と言われて出てくる第一候補が LL(k) パーサモナドだし、じゃあ Applicative は?って言われると Validated みたいなとこある
2023-04-28 17:37:18
Twitter定期的に validated applicative の話になるなって思って validated applicative lang:ja で検索したら僕とがくぞさんと hisaketM さんしか検索結果に出てこないんだけど検索バグッてる?
2023-04-28 19:54:38
Validatedは知ってるけどValidated Applicativeは実は知らなかった twitter.com/Kory__3/status…
2023-04-28 19:59:34
@windymelt Applicative として使うのではなく Validated のメソッドを直接使ってたみたいなパターンですか?
2023-04-28 20:06:28
@Kory__3 あ、ValidatedがApplicativeであるということを意識してなかったです。より強いMonadだという認識が強かった
2023-04-28 20:25:57
CatsとかだとPointedは省略されてApplicativeに包含されてるから忘れがち(ScalazだとPointedとApとでApplicativeになってた気がする)
2023-04-28 18:20:31ライブラリにもよるけど、Applicativeを直接Functorから派生させる流派とPointed(pureを導入する)を挟む流派があるよ(Catsは前者、Scalazは後者)
使うときはあまり考えなくていいよ

Applicative、map2から定義する方法とapで定義する方法がある?(よくわかってない)(pureはオマケだと思う)
2023-04-28 18:17:11
@windymelt def ap[A,B](fab: F[A => B], fa: F[A]) = map2(fab, fa, (fn, a) => fn(a)) def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = ap(fa.map(a => b => f(a,b)), fb)
2023-04-28 18:32:02
@Kory__3 うお〜ありがとうございます。実際どうなのか分からないのですがなんかcurryingみたいな趣がありますね。
2023-04-28 18:39:33Traverse
TraverseはFunctorにtraverseという操作を導入したもので、FunctorとApplicativeの合わせ技的な便利な操作ができるよ
(ScalaMatsuri 2023で見たツイートを末尾に置きました)

次の僕のセッションのスライドはこちらです。「traverse を制する者はコードを制す」gakuzzzz.github.io/slides/control… お手元で見たい場合など #scalamatsuri
2023-04-15 13:58:56