我可以避免在 Idris 的总函数中明确排除无效案例吗?
Can I avoid explicitly discharging invalid cases in total functions in Idris?
考虑以下(非常简化的)示例,该示例通过其值的附加条件来约束数据类型:
data Transport = Car | Foot | Boat
total wheels : (transport : Transport) -> {auto hasWheels : transport = Car} -> Int
wheels Car {hasWheels = Refl} = 4
wheels Foot {hasWheels = Refl} impossible
wheels Boat {hasWheels = Refl} impossible
有什么方法可以省略或总结 impossible
个案例,并且仍然让 Idris 将函数视为整体?如果我确实遗漏了一个案例,我会得到类似
的东西
Main.wheels is not total as there are missing cases
我也不能只有一个包罗万象的情况,因为编译器不知道 _
不能是 Car 所以第二行不进行类型检查:
wheels Car {hasWheels = Refl} = 4
wheels _ {hasWheels = Refl} impossible
这给了
wheels _ is a valid case
我仔细阅读了 中的想法,但没有看到任何有用的方法。
真正的代码是这样简化而来的,有很多case需要一个一个单独的排出,非常笨重。
我更仔细地研究了 中讨论的方法,其中一些确实允许完全省略案例。
我想出了以下似乎最适合我实际情况更复杂的实际用例的方法:
isCar : Transport -> Bool
isCar Car = True
isCar _ = False
BoolToType : Bool -> Type
BoolToType True = ()
BoolToType False = Void
total wheels
: (transport : Transport)
-> {auto hasWheels : BoolToType (isCar transport)}
-> Int
wheels Car = 4
但是我真的不明白为什么 Idris 很乐意在这里而不是在我的原始代码中省略不可能的模式,所以真正解释发生了什么的答案仍然会很有帮助。
考虑以下(非常简化的)示例,该示例通过其值的附加条件来约束数据类型:
data Transport = Car | Foot | Boat
total wheels : (transport : Transport) -> {auto hasWheels : transport = Car} -> Int
wheels Car {hasWheels = Refl} = 4
wheels Foot {hasWheels = Refl} impossible
wheels Boat {hasWheels = Refl} impossible
有什么方法可以省略或总结 impossible
个案例,并且仍然让 Idris 将函数视为整体?如果我确实遗漏了一个案例,我会得到类似
Main.wheels is not total as there are missing cases
我也不能只有一个包罗万象的情况,因为编译器不知道 _
不能是 Car 所以第二行不进行类型检查:
wheels Car {hasWheels = Refl} = 4
wheels _ {hasWheels = Refl} impossible
这给了
wheels _ is a valid case
我仔细阅读了
真正的代码是这样简化而来的,有很多case需要一个一个单独的排出,非常笨重。
我更仔细地研究了
我想出了以下似乎最适合我实际情况更复杂的实际用例的方法:
isCar : Transport -> Bool
isCar Car = True
isCar _ = False
BoolToType : Bool -> Type
BoolToType True = ()
BoolToType False = Void
total wheels
: (transport : Transport)
-> {auto hasWheels : BoolToType (isCar transport)}
-> Int
wheels Car = 4
但是我真的不明白为什么 Idris 很乐意在这里而不是在我的原始代码中省略不可能的模式,所以真正解释发生了什么的答案仍然会很有帮助。