伊德里斯是否真的“严格评估?”

时间:2015-10-02 13:52:45

标签: lazy-evaluation idris

来自哈斯克尔,我正在阅读有关伊德里斯关于懒惰(非严格)的故事。我推测了最近的发行说明,found code类似于以下

myIf : (b : Bool) -> (t : Lazy a) -> (e : Lazy a) -> a
myIf True t e = t
myIf False t e = e

我写了一个简单的阶乘函数来测试它

myFact : Int -> Int
myFact n = myIf (n == 1) 1 (n * myFact (n-1))

我跑了它,它运作了!

> myFact 5
120 : Int

我决定通过将myIf的类型签名更改为

来打破它
myIf : (b : Bool) -> a -> a -> a

我重新加载了idris repl,并再次运行myFact 5期望无限递归。令我惊讶的是,它仍然以同样的方式运作!

idris能否在何时避免严格?为什么这不能永远地归还?

我正在使用Idris 0.9.15,现在和链接的笔记之间没有发行说明,请提及任何更改。

1 个答案:

答案 0 :(得分:17)

解释如下:http://docs.idris-lang.org/en/latest/faq/faq.html#evaluation-at-the-repl-doesn-t-behave-as-i-expect-what-s-going-on

编译时和运行时评估语义是不同的(必须如此,因为在编译时类型检查器需要在存在未知值的情况下计算表达式),并且REPL使用编译时概念,既方便又因为查看类型检查器中表达式的减少方式很有用。

但是,这里还有更多。伊德里斯发现myIf是一个非常小的功能,并决定内联它。所以当编译时myFact实际上有一个看起来有点像的定义:

myFact x = case x == 1 of
                True => 1
                False => x * myFact (x - 1)

所以通常你可以编写像myIf这样的控制结构,而不用担心制作Lazy,因为Idris会将它们编译成你想要的控制结构。同样如下,例如&&||以及短路。