2013-04-05 40 views
6

調試無窮和說我有一個功能(它沒有任何實際的應用,只是一個學術興趣,從而奇怪的方式寫出來,與類羣,應用性函子與不動點組合子)在Haskell

f :: Num a => a -> Sum a 
f = fix ((<>) <$> Sum <*>) 

它是typechecks,但我不能確定它在我測試它之前會做什麼。

如何進行測試和/或調試?我的意思是像幾次迭代後看到結果一樣,如take 10 [1..]

我知道一點關於ghci簡單的調試設施,如:break:step,但步入非終止計算,所以我不能檢查任何東西(它甚至有問題的^C它)。而且我也無法知道如何在Debug模塊中使用trace

任何指針,將不勝感激。

+0

那麼,如果你擴展到'f = fix(\ g - > \ x - > Sum x <> gx)' – phg 2013-04-05 12:31:13

回答

10

ChasingBottomsapproxShow可以幫助你探索部分的評估值:

$ cabal install ChasingBottoms 
$ ghci 
> import Test.ChasingBottoms.ApproxShow 
> import Data.Function 
> approxShow 10 (fix (1:)) 
"[1, 1, 1, 1, 1, 1, 1, 1, 1, _" 

不過,在這裏我們不能直接使用它:求和Integer s是嚴格,不像(:)這是用來建立一個清單。因此應該使用另一種類型。

首先,一些進口(我們還需要能夠獲得Data,使approxShow可以用來展示我們的定製型):

{-# LANGUAGE DeriveDataTypeable #-} 

import Data.Data 
import Data.Monoid 
import Data.Function 
import Control.Applicative 
import Test.ChasingBottoms.ApproxShow 

類型本身(非常基本的),其Num例如:

data S = N Integer | S :+ S 
    deriving (Typeable, Data) 

instance Num S where 
    (+) = (:+) 
    fromInteger = N 
    --other operations do not need to be implemented 

最後,函數:

f :: S -> Sum S 
f = fix ((<>) <$> Sum <*>) 

這裏是我們怎麼能看到什麼f用,比如說做,一個共同的數字,例如1:

*Main> approxShow 5 (getSum (f 1)) 
"(N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _))))" 

當然,它可能是更值得關注的演變:

*Main> Control.Monad.forM_ [0..7] $ \i -> putStrLn $ approxShow i (getSum (f 1)) 
_ 
_ :+ _ 
(N _) :+ (_ :+ _) 
(N 1) :+ ((N _) :+ (_ :+ _)) 
(N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _))) 
(N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _)))) 
(N 1) :+ ((N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _))))) 
(N 1) :+ ((N 1) :+ ((N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _)))))) 
+1

+1,那麼你很容易就能看到它的作用,謝謝分享 – 2013-04-05 13:09:00

+0

謝謝,我似乎沒有雖然:'approxShow 5(f 1)'導致'沒有實例(Data.Data.Data(Sum Integer))',但它仍然可以應用到我的函數中。並且執行'approxShow 10(getSum(f 1))'也不會終止。 – dmedvinsky 2013-04-05 15:19:30

+0

@dmedvinsky:對不起,我的不好(說實話,我以前從來沒有聽說過'Sum',並認爲這是一種自定義類型,所以我沒有打擾自己檢查)。答案已更新。 – Artyom 2013-04-05 17:33:50