Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Idris 用实例证明关于函数的定理_Idris - Fatal编程技术网

Idris 用实例证明关于函数的定理

Idris 用实例证明关于函数的定理,idris,Idris,假设我们有一个函数merge,它只合并两个列表: Order : Type -> Type Order a = a -> a -> Bool merge : (f : Order a) -> (xs : List a) -> (ys : List a) -> List a merge f xs [] = xs merge f [] ys = ys merge f (x :: xs) (y :: ys) = case x `f` y of

假设我们有一个函数merge,它只合并两个列表:

Order : Type -> Type
Order a = a -> a -> Bool

merge : (f : Order a) -> (xs : List a) -> (ys : List a) -> List a
merge f xs [] = xs
merge f [] ys = ys
merge f (x :: xs) (y :: ys) = case x `f` y of
                                   True  => x :: merge f xs (y :: ys)
                                   False => y :: merge f (x :: xs) ys
我们想证明它的一些巧妙之处,例如,合并两个非空列表会产生一个非空列表:

mergePreservesNonEmpty : (f : Order a) ->
                         (xs : List a) -> (ys : List a) ->
                         {auto xsok : NonEmpty xs} -> {auto ysok : NonEmpty ys} ->
                         NonEmpty (merge f xs ys)
mergePreservesNonEmpty f (x :: xs) (y :: ys) = ?wut
检查wut提供给我们的孔类型

到目前为止是有道理的!因此,让我们按照这种类型的建议继续进行案例拆分:

mergePreservesNonEmpty f (x :: xs) (y :: ys) = case x `f` y of
                                                    True => ?wut_1
                                                    False => ?wut_2
似乎有理由希望wut_1和wut_2的类型与merge的case表达式的相应分支相匹配,这样wut_1将类似于非空的x::merge f xs y::ys,可以立即满足,但我们的希望失败了:这些类型与原始wut的类型相同

事实上,唯一的方法似乎是使用with子句:

在这种情况下,类型将如预期的那样,但这会导致对每个with分支重复函数参数,一旦with嵌套,情况会变得更糟,加上with似乎对隐式参数不起作用,但这本身可能值得一提


那么,为什么case在这里没有帮助呢?除了纯实现方面的原因之外,还有什么原因没有将它的行为与的行为相匹配吗?还有其他方法来写这个证明吗?

只有当新信息以某种方式传播到参数时,|左边的东西才是必要的

mergePreservesNonEmpty : (f : Order a) ->
                         (xs : List a) -> (ys : List a) ->
                         {auto xsok : NonEmpty xs} -> {auto ysok : NonEmpty ys} ->
                         NonEmpty (merge f xs ys)
mergePreservesNonEmpty f (x :: xs) (y :: ys) with (x `f` y)
  | True = IsNonEmpty
  | False = IsNonEmpty

-- for contrast
sym' : (() -> x = y) -> y = x
sym' {x} {y} prf with (prf ())
-- matching against Refl needs x and y to be the same
-- now we need to write out the full form
  sym' {x} {y=x} prf | Refl = Refl

至于为什么会出现这种情况,我确实相信这只是实现,但更了解的人可能会对此提出质疑。

只有当新信息以某种方式传播到参数时,|左侧的内容才是必要的

mergePreservesNonEmpty : (f : Order a) ->
                         (xs : List a) -> (ys : List a) ->
                         {auto xsok : NonEmpty xs} -> {auto ysok : NonEmpty ys} ->
                         NonEmpty (merge f xs ys)
mergePreservesNonEmpty f (x :: xs) (y :: ys) with (x `f` y)
  | True = IsNonEmpty
  | False = IsNonEmpty

-- for contrast
sym' : (() -> x = y) -> y = x
sym' {x} {y} prf with (prf ())
-- matching against Refl needs x and y to be the same
-- now we need to write out the full form
  sym' {x} {y=x} prf | Refl = Refl

至于为什么会出现这种情况,我确实认为这只是实施,但更了解的人可能会对此提出质疑。

关于用案例证明问题有一个问题:


因此,在中,我们最终不得不删除此类函数中的所有案例,并定义与案例条件匹配的单独顶级帮助程序,例如。

关于用案例证明问题:


因此,在中,我们最终不得不删除此类函数中的所有案例,并定义与案例条件相匹配的单独顶级助手,例如,like。

我发现传播/影响参数的信息的标准有点模糊,就像,每个案例都会影响我们对参数的了解一样,那么这到底是什么构成的呢?。但是,也许,这更像是一种直觉,随着编写更多的Idris代码,这种直觉会得到改进。这里的反向传播意味着由于with分支中模式的类型而细化参数类型。@Cactus我想我很理解细化的内容,如果这能提供关于给定函数构造函数的更精确信息的话类型但是,在我最初的问题中,在f x y上的匹配这样的情况下,类型有什么改进?同样,这是否意味着每个if/case语句都以某种方式细化了类型?@0xd34df00d Nothing。这就是这个答案的重点。一些匹配揭示了参数的结构,此时必须使用完整形式。这一个没有,所以缩写是有效的。我不知道@Cactus到底想对参数类型说些什么,但重要的是表达式等于什么?参数的类型和模式的类型。在sym'中,除非x和y是相同的,否则Refl模式不会很好地类型化,因此我们对它们进行了细化以使其很好地类型化。布尔的一场比赛总是打字很好,什么也没告诉我们。@HTNW啊,我开始学习阅读,不知何故,我完全错过了第一次缺少左边的东西。现在我完全明白你的意思了,谢谢!我发现传播/影响论点的信息的标准有点模糊,比如,每个案例都会影响我们对论点的了解,那么到底是什么构成了这个?。但是,也许,这更像是一种直觉,随着编写更多的Idris代码,这种直觉会得到改进。这里的反向传播意味着由于with分支中模式的类型而细化参数类型。@Cactus我想我很理解细化的内容,如果这能提供关于给定函数构造函数的更精确信息的话类型但是,在我最初的问题中,在f x y上的匹配这样的情况下,类型有什么改进?同样,这是否意味着每个if/case语句都以某种方式细化了类型?@0xd34df00d Nothing。这就是这个答案的重点。一些匹配揭示了参数的结构,此时必须使用完整形式。这一个没有,所以缩写是有效的。我不知道@Cactus到底想对参数类型说些什么,但重要的是表达式等于什么?参数的类型和模式的类型。在sym'中,除非x和y是相同的,否则Refl模式不会很好地类型化,因此我们对它们进行了细化以使其很好地类型化。布尔的比赛总是打字很好,什么也没告诉我们。@HTNW啊,我得学习阅读,不知怎么地完成了 莱利第一次错过了左路的一切。现在我完全明白你的意思了,谢谢!你甚至不需要foo1间接寻址,我只需要在f上拆分大小写就可以得到相同的行为。实际上,这与我的下一个问题非常接近,所以我想我也会问这个问题。你甚至不需要foo1间接寻址,我通过在f上拆分大小写得到相同的行为。实际上,这与我的下一个问题非常接近,所以我想我也会问这个问题。
mergePreservesNonEmpty : (f : Order a) ->
                         (xs : List a) -> (ys : List a) ->
                         {auto xsok : NonEmpty xs} -> {auto ysok : NonEmpty ys} ->
                         NonEmpty (merge f xs ys)
mergePreservesNonEmpty f (x :: xs) (y :: ys) with (x `f` y)
  | True = IsNonEmpty
  | False = IsNonEmpty

-- for contrast
sym' : (() -> x = y) -> y = x
sym' {x} {y} prf with (prf ())
-- matching against Refl needs x and y to be the same
-- now we need to write out the full form
  sym' {x} {y=x} prf | Refl = Refl