首页 > 解决方案 > 尝试使用 if 跟踪函数

问题描述

expmod :: Integer -> Integer -> Integer -> Integer
expmod a n m | trace (show (a n m)) False = undefined
expmod a 0 m = 1
expmod a n m = let (q,r) = divMod n 2
               ans = expmod a q m
           if r == 0 then let ans = ans*ans `mod` m 
               in trace ("-->" ++ show ans) ans
           else let ans = ans*ans*a `mod` m
               in trace ("-->" ++ show ans) ans

我不确定为什么它在 if 语句中失败

error: parse error on input `if'
   |
37 |                if (r == 0) then let ans = ans*ans `mod` m
   |                ^^

如何跟踪具有 if 语句的函数?

标签: haskell

解决方案


眼前的问题

要回答您的直接问题,您需要in使用您的let(下面代码中第三行的开头):

expmod a n m = let (q,r) = divMod n 2
                   ans   = expmod a q m
               in  if r == 0 then let ans = ans*ans `mod` m 
                                  in  trace ("-->" ++ show ans) ans
                             else let ans = ans*ans*a `mod` m
                                  in  trace ("-->" ++ show ans) ans

其他提示

当您使用 时let ans =,您正在定义ans,因此ans等号右侧的任何内容都将引用等号ans左侧的 ,而不是任何ans其他地方定义的内容。因此,这将失败:

let ans = ans*ans `mod` m

就像是凭空说的一样let x = x*x `mod` m。它只会给出无限递归,所以对两个anses 使用两个不同的变量名。


第三,更简单的方法是使用traceShowId :: Show a => a -> a,它跟踪具有Show实例的值。traceShowId x计算结果为x,因此您可以在想要使用的地方使用它x。它也有痕迹x。例如:

expmod a n m = let (q,r) = divMod n 2
                   ans   = expmod a q m
               in  traceShowId $ if r == 0 then ans*ans   `mod` m 
                                           else ans*ans*a `mod` m

这样打字就少多了。trace "vvv" . traceShowId $如果箭头很重要,您也可以使用。


推荐阅读