class (Functor f, Functor g) => Adjunction f g | f -> g, g -> f where
  unit :: a -> g (f a)
  counit :: f (g a) -> a

ここで一行目のAdjunction f g | f -> g, g -> f で縦棒|は何を表しているんですか?

Haskellのクラス宣言における縦棒|は関数従属性(Functional Dependency)を表しています。具体的にはAdjunction f g | f -> g, g -> fという宣言は、fが決まればgが一意に決まり、逆にgが決まればfが一意に決まるという依存関係を表しています。

関数従属性は、型クラスのインスタンスが一意に決定できるようにするためのものです。もし同じ型に対して複数のインスタンスが存在すると、コンパイラはどのインスタンスを選べば良いか判断できずエラーとなります。関数従属性を用いることで、特定の型が与えられた時に対応するインスタンスが一意に定まることを保証します。この機能は、Haskellのマルチパラメータ型クラス(Multi-parameter Type Classes)と組み合わせて使われます。Source 2

具体的にAdjunction f g | f -> g, g -> fという宣言を見てみましょう。これはAdjunction型クラスがfgの2つの型パラメータを持つマルチパラメータ型クラスであり、fgに、gfに依存していることを示しています。これにより、fgのどちらか一方が決まれば、もう一方の型も一意に決まることが保証されます。Source 1

例えば、以下のような型クラスのインスタンス宣言があったとします。

instance Adjunction Maybe [] where
  unit = return
  counit = head

この場合、関数従属性f -> g, g -> fのおかげで、fMaybeであるならばg[]でなければならず、逆にg[]であるならばfMaybeでなければならないと決まります。したがって、fgの型が決まった時点で、Adjunctionのインスタンスが一意に決まることが保証されます。

  • Rustの関連型っぽい?