我用递归函数在Haskell中实现一些数论函数的幂运算。我正在使用QuickCheck库来测试我的实现。为了简化我的测试,我使用了基库中的Natural数据类型,在quickcheck-instances库中定义的Natural任意实例,以及以下从Nat转换到Natural和从Natural转换到Nat的函数,考虑的是我自己定义的数据Nat:
data Nat = Zero | Succ Nat
natToNatural :: Nat -> Natural
natToNatural Zero = 0
natToNatural (Succ n) = 1 + natToNatural n
naturalToNat :: Natural -> Nat
naturalToNat 0 = Zero
naturalToNat n = Succ (naturalToNat (n - 1))
在自然数上使用以下递归:
recNat :: a -> (Nat -> a -> a) -> Nat -> a
recNat a _ Zero = a
recNat a h (Succ n) = h n (recNat a h n)
我的幂函数是
expR :: Nat -> Nat -> Nat
expR m n = recNat (Succ Zero) (\ _ y -> multR m y) n
prop_Exp :: Natural -> Natural -> Bool
prop_Exp m n = natToNatural (expR m' n') == m ^ n
where
m' :: Nat
m' = naturalToNat m
n' :: Nat
n' = naturalToNat n
main :: IO ()
main = quickCheck prop_expR
*** Exception: stack overflow
正如chi所说,NAT
类型将数字表示为递归数据结构。我认为它与[()]
同构,但我可能错了······
当然,转换函数和recnat
都不是尾部递归的,所以当使用10^10
这样的东西时,它们将为数十亿个元素建立thunk。从较大的数字中得到堆栈溢出并不奇怪。
您可以告诉QuickCheck限制生成的值的范围。choose
函数是该问题的通用解决方案,但是AFAICTnatural
没有random
实例。相反,您可以使用chooseenum
,因为natural
确实有enum
实例。
testProperty "Multiplication" $ do
x <- choose @Integer (0, 25)
y <- choose (0, 25)
return $ x * y === toNum (multiplyF (fromNum x) (fromNum y))
testProperty "Increment" $ do
i <- choose @Integer (0, 1e4)
return $ i + 1 === toNum (incF (fromNum i))
我们从右到左都知道并爱/恨作文: 什么是自然/从左到右组合的“最标准”操作符(如在某种公共库中):
作为一个Haskell新手,我不明白为什么表达式抛出异常和函数组合必须与运算符一起应用-它右边的表达式不需要进一步计算,因为它只是一个。编译它的另一种方法是将在括号中,但是与,那么为什么把它放在括号中可以编译表达式呢?
考虑Python中的这个基本递归: 根据斐波那契数列的(n-1)(n-2)函数,这是有道理的。 Python如何执行包含另一个递归的递归,这个递归不在同一代码行内,而是在同一代码行内?“finobacci(number-1)”是否完成所有递归,直到它到达“1”,然后它对“fibonacci(number-2)”做同样的事情,并将它们相加? 作为比较,下面的递归函数将一个数“x”提升为“y”的幂,我
我正在从事一个基于C中自定义数据结构list\t的项目。这是可以帮助我操作这个list\t的预定义函数,我被要求编写的函数叫做insert\u list(list\u t,list\u t,int),它是尾部递归的。 我要编写的insert_list()函数接受两个输入,类型为list_t和一个保证不大于第一个list_t大小的额外整数n,并返回另一个list_t,其中包含第一个list_t中的前
这个递归编码是错误的还是仅仅是那个控制台。即使执行递归,log()也不总是被执行? 在控制台中执行testrecursion不会返回任何错误。 信息控制台日志显示 再次执行测试递归会在信息控制台日志中显示这一点。 第三次执行testrecursion会在信息控制台日志中显示这一点。 在对此进行了数十次测试后,递归步骤似乎偶尔被调用。输出似乎是随机的。预期输出为 这是否看起来像递归正确发生,只是控制
我有一个家庭作业问题,它给出了一个递归函数,我必须使用尾部递归来实现它。函数为f(0)=1 f(n)=1 2*f(n-1) 我并不擅长尾部递归,我试着查找示例,但我发现的都是没有斐波那契序列的示例,这没有多大帮助。 我真正拥有的是 我知道尾递归基本上每次调用都计算函数,我只是不知道如何实现它。 编辑:我打了一个错字f(n)应该是1 2*f(n-1)