我试图在Idris中实现尽可能多的System F(多态lambda演算)。我现在面临一个问题,我想用一个例子来证明:
data Foo = Bar Nat
Eq Foo where
(Bar _) == (Bar _) = True
data Baz: Foo -> Type where
Quux: (n: Nat) -> Baz (Bar n)
Eq (Baz f) where
(Quux a) == (Quux b) = ?todo
如您所见,任何两个Foo
值都相等。我现在希望能够在Baz f
上定义相等性时使用这一事实:Quux a
类型Baz (Foo a)
,Quux b
类型Baz (Foo b)
和{{ 1}}和Foo a
是平等的,所以我的直觉是这应该有效。但编译器拒绝它,说Foo b
和Baz (Foo a)
之间的类型不匹配。
有没有办法让这项工作?这个问题阻止我实现alpha等价。
答案 0 :(得分:1)
不幸的是,我对系统F和alpha等效性几乎一无所知,所以请用一粒盐。但是,在您发布的特定情况中解决问题的一种方法是:
data Foo = Bar
bar: Nat -> Foo
bar _ = Bar
Eq Foo where
Bar == Bar = True
data Baz: Foo -> Type where
Quux: (n: Nat) -> Baz (bar n)
Eq (Baz f) where
(Quux a) == (Quux b) = ?todo
据我了解,Eq
个实例用于运行时的等式检查。没有咨询他们以检查两种类型是否统一。
您希望所有Foo
个实例在类型级别上统一,因此实际上只能有一个;我们只需称它为Bar
。您在代码中使用的该名称的数据构造函数已降级为函数bar
,只返回Foo
个唯一Bar
实例Nat
。< / p>
Eq
的{{1}}实施现在更加微不足道了(虽然在这种情况下不再需要),Foo
现在使用Quux
代替bar
因此,它创建的所有Bar
实例实际上都共享相同的类型Baz
。
答案 1 :(得分:1)
为什么不为异质平等定义另一个运算符并使用它呢?
module Main
infix 5 ~=
interface HEq a b where
(~=) : a -> b -> Bool
-- This will make ~= work as replacement for ==
Eq a => HEq a a where
(~=) = (==)
data Foo = Bar Nat
Eq Foo where
(Bar _) == (Bar _) = True
data Baz : Foo -> Type where
Quux : (n : Nat) -> Baz (Bar n)
HEq (Baz a) (Baz b) where
(Quux x) ~= (Quux y) = True -- do whatever you want here
main : IO Unit
main = do
putStrLn $ show $ 5 ~= 5 -- prints True
putStrLn $ show $ 5 ~= 6 -- prints False
putStrLn $ show $ (Quux 10) ~= (Quux 20) -- prints True