【发布时间】:2016-06-01 20:27:13
【问题描述】:
我已经编写 Haskell 有一段时间了,但想尝试使用 Idris 语言和依赖类型进行一些实验。我玩了一点,并阅读了基本文档,但是我想表达某种风格的功能,并且不知道如何/是否可能。
以下是我想知道是否可以表达的几个例子:
first:一个接受两个自然数但只检查第一个是否小于另一个的函数。所以f : Nat -> Nat -> whatever nat1 小于 nat2。这个想法是,如果像 f 5 10 这样调用它会起作用,但如果我像 f 10 5 这样调用它,它将无法进行类型检查。
second:一个函数,它接受一个字符串和一个字符串列表,它只检查第一个字符串是否在字符串列表中。
在 Idris 中可以实现这样的功能吗?如果是这样,您将如何实现上述简单示例之一?谢谢!
编辑:
在几位用户的帮助下,编写了以下解决方案函数:
module Main
import Data.So
f : (n : Nat) -> (m : Nat) -> {auto isLT : So (n < m)} -> Int
f _ _ = 50
g : (x : String) -> (xs : List String) -> {auto inIt : So (elem x xs)} -> Int
g x xs = 52
main : IO ()
main = putStrLn $ show $ g "hai" ["test", "yo", "ban", "hai", "dog"]
这些当前的解决方案不适用于大型案例。例如,如果您运行 f 的数字超过几千,则需要永远(不是字面意思)。我认为这是因为类型检查当前是基于搜索的。一位用户评论说,可以通过自己编写证明来为自动提供提示。假设这是所需要的,如何为这些简单案例中的任何一个编写这样的证明?
【问题讨论】:
-
我对 Idris 不太熟悉,但肯定有可能。我快速浏览了stdlib - 第一个类似于
f : (n m : Nat) -> { isLT : Prelude.Nat.LT n m } -> X,第二个类似于g : (x : String) (xs : List String) -> { in : Prelude.List.elem x xs = True } -> Y。 (=是命题相等,不确定 Idris 用于此的符号吗?)也许还有其他更好的编码,但这些仅适用于 stdlib。 -
@user2407038、it's
{auto isLT : Prelude.Nat.LT n m}和{auto in : Prelude.List.elem x xs = True}。 -
这很棒@user2407038 我注意到当我这样做
f 50 100时一切都很好。但是当我做f 500 1000时,它说它找不到解决方案。我认为那是因为它是蛮力的?有没有一种方法可以得到我想要的结果,它适用于更大的数字? -
@HarpoRoeder 当你写
{auto ...}时——根据另一位评论者提供的非常有用的链接——“如果他们有参数,它将递归搜索到最大深度100。”。您可以简单地自己提供证明,而不是依赖auto。auto也将尝试“任何具有适当返回类型且标有 %hint 注释的函数。”所以你可以试试(仍然必须自己写证明)。同样,对 idris 不太熟悉——尤其是这些细节。 -
@Harpo Roeder,试试
{auto isLT : So (n < m)}。更多关于Sohere。
标签: haskell dependent-type idris