是否可以在 Idris 中使模式匹配惰性化?
Is it possible to make pattern matching lazy in Idris?
在 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
)。
除了了解是否有办法解决这个问题之外,我还很高兴知道 Idris 为什么会这样。
好吧,如果我没理解错的话,这可行
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
在 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
)。
除了了解是否有办法解决这个问题之外,我还很高兴知道 Idris 为什么会这样。
好吧,如果我没理解错的话,这可行
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