除了 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
这表示关于两种类型相等的定理。ega
等价于b
is 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 中。它通过从类型世界中的值世界复制数据来做到这一点。我认为它还不能处理重复的值级函数,如果是这样,我的直觉是这可能太复杂而无法处理。