我们说我有一个模块。
module A
%default total
%access export
data D = A | B
Value1: D
Value1 = A
Value2: D
Value2 = A
由于Value1
和Value2
的实现是隐藏的,我希望不可能在另一个模块中构建证明prf: Value1 = Value2
,但事实上它是可能的:
module B
import A
%default total
prf: Value1 = Value2
prf = Refl
当我将Value2
的定义更改为
Value2: D
Value2 = Value1
我收到了预期的错误。
现在,我通过扩展模块D
并实现A
来公开DecEq D
的相等性。现在,在其他模块中运行时可以获得Value1 = Value2
的实例:
main : IO ()
main = case decEq Value1 Value2 of
Yes prf => putStrLn "Got instance of Value1 = Value2."
No _ => putStrLn "This should not happen."
我希望使用decEq
它也可以在类型检查时获得此证明的实例。我试过了
prf: Value1 = Value2
prf with (decEq Value1 Value2)
| Yes p = p
| No _ impossible
还有这个非常讨厌的解决方案:
%language TypeProviders
prfProvider : IO (Provider (Value1 = Value2))
prfProvider = do case decEq Value1 Value2 of
Yes p => pure (Provide p)
No _ => pure (Error "This should not happen.")
%provide (prf: Value1 = Value2) with prfProvider
两种解决方案都不起作用。
现在我的问题是:当Value1 = Value2
定义Value2
时,为什么我可以构建Value2 = A
的实例?并且考虑到DecEq D
的实现,有一种方法可以在编译时获取Value1 = Value2
的实例,如果没有,为什么这样设计呢?