输入验证的命题与布尔值

Propositions vs. boolean values for input validation

我有以下代码:

doSomething : (s : String) -> (not (s == "") = True) -> String
doSomething s = ?doSomething

validate : String -> String
validate s = case (not (s == ""))  of
                  False  => s
                  True => doSomething s 

检查输入不为空后,我想将其传递给一个只接受经过验证的输入(不接受空字符串)的函数。

据我了解,验证是在运行时进行的 但是类型是在编译时计算的——那是行不通的。有什么解决方法吗?

在玩代码时我还注意到:

:t (("la" == "") == True)
"la" == "" == True : Bool

但是

:t (("la" == "") = True)
"la" == "" = True : Type

为什么类型不同?

这与运行时与编译时无关,因为您在 validate 中编写了两个分支,它们静态地处理空输入和非空输入情况;在运行时,您只需在两者之间进行选择。

您的问题是 Boolean blindness:如果您有一个类型为 Bool 的值,那么,一个位可能会向任何方向移动。这就是 == 给你的。

另一方面,

= 用于命题相等:类型(-as-proposition)a = b 的唯一构造函数是 Refl : a = a,因此通过模式匹配a = b 类型的值,您了解到 ab 真正相等。

通过将不等式作为命题传递给 doSomething:

,我能够让你的示例工作
doSomething : (s : String) -> Not (s = "") -> String
doSomething "" wtf = void $ wtf Refl
doSomething s nonEmpty = ?doSomething

validate : String -> String
validate "" = ""
validate s = doSomething s nonEmpty
  where
    nonEmpty : Not (s = "")
    nonEmpty Refl impossible

As far as I understand the validation is taking place during runtime but the types are calculated during compile time - thats way it doesn't work.

这是不正确的。它不起作用,因为

  • 我们需要with形式来执行依赖模式匹配,i。 e.根据从特定数据构造器获得的信息对上下文进行替换和细化。

  • 即使我们在这里使用 with,当我们进行模式匹配时,not (s == "") 不在上下文中的任何地方,因此没有什么可以重写(在上下文中) ,我们无法在稍后调用 doSomething.

  • 时证明 not (s == "") = True 相等

我们可以在这里使用包装数据类型,让我们保存特定模式等于我们匹配的原始表达式的证明:

doSomething : (s : String) -> (not (s == "") = True) -> String
doSomething s = ?doSomething

data Inspect : a -> Type where
  Match : {A : Type} -> {x : A} -> (y : A) -> x = y -> Inspect x

inspect : {A : Type} -> (x : A) -> Inspect x
inspect x = Match x Refl

validate : String -> String
validate s with (inspect (not (s == "")))
  | Match True  p = doSomething s p
  | Match False p = s