伊德里斯真的是 "strictly evaluated?"
Is Idris really "strictly evaluated?"
来自 Haskell,我正在阅读 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 和 none 从现在到链接的发行说明,请提及任何更改。
编译时和运行时间评估语义不同(必然如此,因为在编译时类型检查器需要在存在未知值的情况下评估表达式),并且 REPL 使用编译时概念,这既是为了方便,也是因为在类型检查器中查看表达式如何减少是很有用的。
但是,这里还有一些事情要做。 Idris 发现 myIf
是一个非常小的函数,因此决定将其内联。所以编译时 myFact
实际上有一个看起来有点像的定义:
myFact x = case x == 1 of
True => 1
False => x * myFact (x - 1)
所以通常你可以编写像 myIf
这样的控制结构而不用担心制作东西 Lazy
,因为 Idris 无论如何都会将它们编译成你想要的控制结构。同样适用于,例如&&
和 ||
以及短路。
来自 Haskell,我正在阅读 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 和 none 从现在到链接的发行说明,请提及任何更改。
编译时和运行时间评估语义不同(必然如此,因为在编译时类型检查器需要在存在未知值的情况下评估表达式),并且 REPL 使用编译时概念,这既是为了方便,也是因为在类型检查器中查看表达式如何减少是很有用的。
但是,这里还有一些事情要做。 Idris 发现 myIf
是一个非常小的函数,因此决定将其内联。所以编译时 myFact
实际上有一个看起来有点像的定义:
myFact x = case x == 1 of
True => 1
False => x * myFact (x - 1)
所以通常你可以编写像 myIf
这样的控制结构而不用担心制作东西 Lazy
,因为 Idris 无论如何都会将它们编译成你想要的控制结构。同样适用于,例如&&
和 ||
以及短路。