如何从函数内部打印变量?

时间:2016-09-28 19:46:13

标签: haskell

所以我有一个主函数(foo)递归调用另外两个函数(step1& step2)。 foo会将a1添加到a2 count次,然后返回(a1,a2)。如何在每一步打印变量count,a1和a2?

-- adds a1 to a2 a `count` number of times
-- returns (a1, a2) once count reaches 0
foo :: Integer -> Integer -> Integer -> (Integer, Integer)
foo count a1 a2 | count == 0 = (a1,a2)
                | otherwise = foo count' a1' a2'
                where (count', a1', a2') = let (count'', a1'', a2'') = step1 count a1 a2
                                           in step2 count'' a1'' a2''

-- adds a2 to a1. How to print out count, a1 and a2' here?
step1 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step1 count a1 a2 = (count, a1, a2')
    where
        a2' = a1 + a2

-- decrements count by 1. How to print out count', a1 and a2 here? Or can I do these prints somewhere in the `foo` function? 
step2 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step2 count a1 a2 = (count', a1, a2)
    where
        count' = count - 1

这是来自更大代码库的代码的简化版本。我愿意采用不同的方法。我正在寻找的示例输出是:

$> foo 3 4 5

3 4 5

3 4 9

2 4 9

2 4 13

1 4 13

1 4 17

0 4 17

(4,17)

编辑:我刚刚意识到我可能会将中间结果存储在列表中,然后从该列表中打印出来。但我是否认为我必须将列表作为参数传递给函数?

2 个答案:

答案 0 :(得分:7)

您必须更改foo并使其在IO monad中运行。实际上这个"标签"该函数是不纯的(即它具有副作用,例如在stdout上打印),允许它调用诸如print之类的函数。这是一个例子:

foo :: Integer -> Integer -> Integer -> IO (Integer, Integer)
foo count a1 a2 = do
    print (count, a1, a2)
    case count of
        0 -> do
            print (a1,a2)
            return (a1,a2)
        _ -> do
            let (count'', a1'', a2'') = step1 count a1 a2
                (count', a1', a2') = step2 count'' a1'' a2''
            foo count' a1' a2'

注意:如果您要打印这些值以进行调试,则可以使用Debug.Trace中显示的{{1}}。你应该这样做只是出于调试目的而没有其他原因。

答案 1 :(得分:7)

仅出于调试目的,您可以使用Debug.Trace。例如:

import Debug.Trace

-- adds a2 to a1. How to print out count, a1 and a2' here?
step1 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step1 count a1 a2 = traceShowID (count, a1, a2')
    where
        a2' = a1 + a2

-- decrements count by 1. How to print out count', a1 and a2 here? Or can I do these prints somewhere in the `foo` function? 
step2 :: Integer -> Integer -> Integer -> (Integer, Integer, Integer)
step2 count a1 a2 = traceShowID (count', a1, a2)
    where
        count' = count - 1

traceShowID :: Show a => a -> a基本上是id,其副作用(未公布)也会根据show打印参数的字符串表示。