输入验证的命题与布尔值

时间:2015-09-13 21:54:23

标签: idris

我有以下代码:

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

为什么类型不同?

2 个答案:

答案 0 :(得分:2)

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

你的问题是Boolean blindness:如果你的类型为Bool,那就是一个可能已经走了一个位的那个。这是==给你的。

另一方面,

=用于命题相等:该类型的唯一构造函数(-as-proposition)a = bRefl : 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

答案 1 :(得分:1)

  

据我所知,验证是在运行时进行的   但是类型是在编译期间计算的 - 这就是它   不起作用。

这不正确。它没有用,因为

  • 我们需要with表单来执行依赖模式匹配,即。即根据从特定数据构造函数获得的信息对上下文执行替换和细化。

  • 即使我们在这里使用with,当我们进行模式匹配时,not (s == "")在上下文中的任何位置都没有,因此无需重写(在上下文),当我们想要致电not (s == "") = True时,我们无法证明doSomething平等。

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

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