2016-09-28 55 views
2

所以我有一個主函數(foo)遞歸調用兩個其他函數(step1 & step2)。 foo會將a1添加到a2 a 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

(4,17)

編輯:我才意識到我大概可以存儲在一個列表中間結果,然後從該列表打印。但是,我認爲我必須通過列表作爲函數的參數嗎?

回答

5

您必須更改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如圖chepner's answer。您應該只是爲了調試目的而做到這一點,沒有其他原因。

+0

感謝您的回覆。這可能適用於foo函數,但我需要在每個步驟函數中打印(而不僅僅是在您的示例中的末尾)。所以我將不得不改變step1和step2的輸出類型,這會在foo函數中引起一些綁定問題。想法? 編輯:沒關係。我現在看到你的解決方案完美地工作。非常感謝你。 –

4

僅用於調試目的,您可以使用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也打印參數的字符串表示(突擊)副作用。