我有以下代码:
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
为什么类型不同?
答案 0 :(得分:2)
这不是关于运行时与编译时的关系,因为你在validate
中编写两个分支,静态地处理空输入和非空输入情况;在运行时,您只需在两者之间进行选择。
你的问题是Boolean blindness:如果你的类型为Bool
,那就是一个可能已经走了一个位的那个。这是==
给你的。
=
用于命题相等:该类型的唯一构造函数(-as-proposition)a = b
是Refl : a = a
,因此通过模式匹配对于值{键入a = b
,您了解到a
和b
真正相同。
通过将非平等作为命题传递给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