TomMD の回答に加えて、Agda を使用して同じ効果を得ることができます。型クラスはありませんが、ほとんどの機能 (動的ディスパッチを除く) をレコードから取得できます。
record Direction (a : Set) : Set₁ where
field
turnLeft : a → a
turnRight : a → a
commLaw : ∀ x → turnLeft (turnRight x) ≡ turnRight (turnLeft x)
投稿を編集して、なぜ Haskell でこれができないのかという質問に答えようと思いました。
Haskell (+ 拡張機能) では、上記の Agda コードで使用されているように同等性を表すことができます。
{-# LANGUAGE GADTs, KindSignatures, TypeOperators #-}
data (:=:) a :: * -> * where
Refl :: a :=: a
これは、2 つの型が等しいという定理を表しています。たとえばa
is と同等b
ですa :=: b
。
それらが同等である場合、コンストラクターを使用できますRefl
。これを使用して、定理 (型) の証明 (値) に対して関数を実行できます。
-- symmetry
sym :: a :=: b -> b :=: a
sym Refl = Refl
-- transitivity
trans :: a :=: b -> b :=: c -> a :=: c
trans Refl Refl = Refl
これらはすべて型が正しいため、真です。しかし、これは;
wrong :: a :=: b
wrong = Refl
明らかに間違っており、実際に型チェックに失敗します。
ただし、これらすべてを通じて、値と型の間の壁は破られていません。値、値レベルの関数、および証明は、依然としてコロンの片側に存在します。型、型レベル関数、および定理は互いに共存しています。turnLeft
とturnRight
は値レベルの関数であるため、定理に関与することはできません。
AgdaとCoqは依存型言語であり、バリアが存在しないか、クロスオーバーが許可されています。Strathclyde Haskell Enhancement (SHE)は、Haskell コードのプリプロセッサであり、DTP の効果の一部を Haskell にチートすることができます。これは、値の世界のデータを型の世界に複製することによって行われます。値レベル関数の複製をまだ処理しているとは思いません。もしそうなら、これは複雑すぎて処理できないのではないかと思います。