【问题标题】:Idris - proof on inductive stepIdris - 归纳步骤的证明
【发布时间】:2017-10-06 08:13:16
【问题描述】:

考虑以下函数

tryMove : (diskNumber : Nat) -> (from: Peg) -> (to: Peg)-> {default Oh prf: So (from /= to)} -> Disposition diskNumber -> Maybe (Disposition diskNumber)
tryMove Z from to [] = Nothing
tryMove (S k) from to (smallestDiskPosition :: restOfTheDisposition) =
        map (smallestDiskPosition ::) (tryMove k from to restOfTheDisposition)

尝试编译时出现以下错误:

When checking argument prf to Hanoi.tryMove:
        Type mismatch between
                So True (Type of Oh)
        and
                So (from /= to) (Expected type)

        Specifically:
                Type mismatch between
                        True
                and
                        not (Hanoi.Peg implementation of Prelude.Interfaces.Eq, method == from to)

关于tryMove 的递归调用。 如果我明确地传递{prf},如

tryMove : (diskNumber : Nat) -> (from: Peg) -> (to: Peg)-> {default Oh prf: So (from /= to)} -> Disposition diskNumber -> Maybe (Disposition diskNumber)
tryMove Z from to [] = Nothing
tryMove (S k) from to {prf} (smallestDiskPosition :: restOfTheDisposition) =
        map (smallestDiskPosition ::) (tryMove k from to {prf} restOfTheDisposition)

它编译正确。

为什么 Idris 不能在归纳步骤中自动检测证明,而在函数的正常调用中能够做到?

编辑:

这里有一个完整的使用要点:https://gist.github.com/marcosh/d51479ea08e8522560713fd1e5ca9624

【问题讨论】:

    标签: idris


    【解决方案1】:

    您为 prf 提供默认值 (Oh),因此 Idris 试图将 Oh 传递给递归调用。 Oh 的类型为 So True,Idris 预计 prf 的类型为 So (from /= to),但由于您不破坏 tofrom,Idris 无法知道 from /= to 的值,这就是为什么您查看该错误消息。

    您可以更改签名以包含{auto prf: So (from /= to)} 或完全删除prf 参数,因为您实际上并没有使用它,您只需将其传递给递归调用而不做任何修改。

    【讨论】:

    • 感谢您的回答。我不明白一件事。 ` 是什么意思,因为你不破坏往返,Idris 无法知道 from /= to? from` 和 to 的值与初始调用相同。如果一开始就不同,为什么伊德里斯就不能理解之后的不同呢?此外,你说的破坏tofrom是什么意思?我怎么能这样做?
    • 你传递 Oh 类型为 So True 的地方 Idris 需要一个类型为 So (from /= to) 的值,只要 from /= toTrue 在定义上相等,Idris 将允许你这样做,如果from /= to 计算结果为True,则在这种情况下更精确。但是要评估(/=) 函数应用程序,您需要知道这两个参数到底是什么。 Idris 不知道fromto 不相等。模式匹配是您传播信息的方式。因此,帮助 Idris 的一种极其难看的方法是在 fromto 上进行模式匹配——这将生成 9 个子句(其中 3 个是不可能的)