尝试使用if跟踪功能

时间:2018-10-08 19:17:02

标签: haskell

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语句的函数?

1 个答案:

答案 0 :(得分:5)

眼前的问题

要回答您的紧迫问题,您需要inlet一起使用(下面代码中第三行的开头):

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。它只会提供无限递归,因此请为两个ans使用两个不同的变量名。


第三,更简单的方法是使用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 $