アドホック多相
異なる型の引数に適用でき、引数の型に応じて個別の実装に切り替わる(dispatchされる)関数
「異なる型」というのは部分型関係すらもないという意味
そもそもHaskellやRustには部分型がない
ad-hoc polymorphism
アドホック多相を前面に押し出していない言語であっても組み込み演算子がアドホック多相になっていることが多い
+ が int にも float にも使えたりする
OCaml は演算子からもアドホック多相を排除することでとても強力な型推論を得ている ある1つの名前の関数/メソッドを多重に定義すること。
トレイトそのものは型ではなく、型引数の制約として使う
実質型クラスらしい
code:rs
// 引数部でのimpl IteratorはトレイトIteratorを実装した任意の型を受け取る、の意
fn sum<A>(iter: impl Iterator<Item = A>) -> Option<A>
// 型引数の制約として与えられるトレイトにstd::ops::Addで加算の結果もAになるような型Aを指定
where A: std::ops::Add<Output = A>
{
// accとvalはともにA型で、A型がstd::ops::Addを実装しているので+演算ができる
iter.reduce(|acc, val| acc + val)
}
fn main() {
println!("{}", sum(1..=3).unwrap()); // レンジ
println!("{}", sum(vec!1, 2, 3.into_iter()).unwrap()); // ベクタ }
Rustの型推論は相当強い部類だが、関数のシグネチャは省略できない決まりになっている
Rustのトレイトと同じで型ではないが、HaskellとPureScriptにはレシーバをとるOOP的な意味でのメソッドがなく使用感がやや異なる
組み込み演算子も型クラスを用いて定義されているので f a b = a + b のような関数を書けば Num 型クラスが推論される。
.NETに型システムがあるせいで型システムの拡張が難しい
コンパイル(バイトコードへの変換)時に展開されて消えるインライン関数の中ではいろいろできる SRTPは名前(statically resolved)の通り静的に解決される
SRTPはメンバ制約を持てる
このメンバを持っているような型を型引数に割り当てできる