在Haskell中,我们可以在不收到运行时错误(ref)的情况下执行以下操作:
mytake 0 _ = []
mytake _ [] = []
mytake n (x:xs) = x : mytake (n-1) xs
print( mytake 0 (undefined::[Int]) )
在Idris中,我们可以做一个类似的定义,但行为是不同的:
mytake : Integer -> List a -> List a
mytake 0 _ = []
mytake _ [] = []
mytake n (x::xs) = x :: mytake (n-1) xs
printLn( mytake {a = Nat} 0 ?undefined )
在这种情况下,我们得到ABORT: Attempt to evaluate hole Main.undefined
。我知道Idris不是一种懒惰的语言,但我的印象是模式匹配参数可能与评估数据结构的逻辑分开(可以在Idris中回避,例如Stream
)。
除了理解是否有办法解决这个问题外,我还要了解伊德里斯为何会以这种方式行事。
答案 0 :(得分:1)
好吧,如果我理解正确,这可能有效
module Main
mytake : Integer -> Lazy (List a) -> List a
mytake 0 _ = []
mytake _ [] = []
mytake n (x::xs) = x :: mytake (n-1) xs
main : IO ()
main = printLn (mytake {a = Nat} 0 ?undefined)
但是在编译时它给了我奇怪的错误
andrey@linux:~/idris> idris -o test test.idr
idris: src/Idris/Core/CaseTree.hs:(645,1)-(654,51): Non-exhaustive patterns in function varRule
回答你问题的第二部分: 这主要是因为热切的评价更容易预测。这个问题是在一个非正式的常见问题解答中
https://github.com/idris-lang/Idris-dev/wiki/Unofficial-FAQ#why-isnt-idris-lazy