Idris:尝试为 Nat 重新实现 fromInteger 时,完整性检查失败
Idris: totality check fails when trying to re-implement fromInteger for Nat
我有以下代码:
module Test
data Nat' = S' Nat' | Z'
Num Nat' where
x * y = ?hole
x + y = ?hole
fromInteger x = if x < 1 then Z' else S' (fromInteger (x - 1))
我收到有关最后一行的错误消息:
Test.idr:6:5:
Prelude.Interfaces.Test.Nat' implementation of Prelude.Interfaces.Num, method fromInteger is
possibly not total due to recursive path Prelude.Interfaces.Test.Nat' implementation of
Prelude.Interfaces.Num, method fromInteger --> Prelude.Interfaces.Test.Nat' implementation of
Prelude.Interfaces.Num, method fromInteger
该函数应该始终给出一个结果,因为最终 fromInteger 的参数将变得足够小以选择第一种情况。但伊德里斯似乎并不明白这一点。这个函数有什么问题,我该如何解决这个错误?
n - 1
在结构上不小于n
,看这个就观察到Integer
不是归纳型。因此,您需要使用像 assert_smaller
这样的技巧来说服完整性检查器您的函数实际上是完整的(参见 Idris tutorial):
这是它的 current 定义:
assert_smaller : (x : a) -> (y : b) -> b
assert_smaller x y = y
It simply evaluates to its second argument, but also asserts to the totality checker that y
is structurally smaller than x
.
这是 Idris 在其标准库中使用的内容(参见 here)来解决您的问题:
fromIntegerNat : Integer -> Nat
fromIntegerNat 0 = Z
fromIntegerNat n =
if (n > 0) then
S (fromIntegerNat (assert_smaller n (n - 1)))
else
Z
我有以下代码:
module Test
data Nat' = S' Nat' | Z'
Num Nat' where
x * y = ?hole
x + y = ?hole
fromInteger x = if x < 1 then Z' else S' (fromInteger (x - 1))
我收到有关最后一行的错误消息:
Test.idr:6:5:
Prelude.Interfaces.Test.Nat' implementation of Prelude.Interfaces.Num, method fromInteger is
possibly not total due to recursive path Prelude.Interfaces.Test.Nat' implementation of
Prelude.Interfaces.Num, method fromInteger --> Prelude.Interfaces.Test.Nat' implementation of
Prelude.Interfaces.Num, method fromInteger
该函数应该始终给出一个结果,因为最终 fromInteger 的参数将变得足够小以选择第一种情况。但伊德里斯似乎并不明白这一点。这个函数有什么问题,我该如何解决这个错误?
n - 1
在结构上不小于n
,看这个就观察到Integer
不是归纳型。因此,您需要使用像 assert_smaller
这样的技巧来说服完整性检查器您的函数实际上是完整的(参见 Idris tutorial):
这是它的 current 定义:
assert_smaller : (x : a) -> (y : b) -> b assert_smaller x y = y
It simply evaluates to its second argument, but also asserts to the totality checker that
y
is structurally smaller thanx
.
这是 Idris 在其标准库中使用的内容(参见 here)来解决您的问题:
fromIntegerNat : Integer -> Nat fromIntegerNat 0 = Z fromIntegerNat n = if (n > 0) then S (fromIntegerNat (assert_smaller n (n - 1))) else Z