Debugging Haskell中无穷和的调试
假设我有一个函数(它没有任何实际的应用,只是一个学术兴趣,因此编写它的方式很奇怪,有幺半群、应用函子和不动点组合子)Debugging Haskell中无穷和的调试,debugging,testing,haskell,monoids,applicative,Debugging,Testing,Haskell,Monoids,Applicative,假设我有一个函数(它没有任何实际的应用,只是一个学术兴趣,因此编写它的方式很奇怪,有幺半群、应用函子和不动点组合子) f::Num a=>a->Sum a f=固定值(()和) 它会进行类型检查,但在我测试它之前,我不能确定它是否完成了预期的功能 如何进行测试和/或调试?我的意思是在几次迭代后看到结果,就像使用take 10[1..]一样 我对ghci的简单调试工具略知一二,比如:break和:step,但它会进入非终止计算,因此我无法检查任何东西(它甚至对^C有问题)。我也不知道如何在这个函
f::Num a=>a->Sum a
f=固定值(()和)
它会进行类型检查,但在我测试它之前,我不能确定它是否完成了预期的功能
如何进行测试和/或调试?我的意思是在几次迭代后看到结果,就像使用take 10[1..]
一样
我对ghci
的简单调试工具略知一二,比如:break
和:step
,但它会进入非终止计算,因此我无法检查任何东西(它甚至对^C
有问题)。我也不知道如何在这个函数中使用trace
fromDebug
模块
任何提示都将不胜感激。软件包
chasingboots
及其功能可帮助您探索部分评估值:
$ cabal install ChasingBottoms
$ ghci
> import Test.ChasingBottoms.ApproxShow
> import Data.Function
> approxShow 10 (fix (1:))
"[1, 1, 1, 1, 1, 1, 1, 1, 1, _"
然而,这里我们不能直接使用它:对整数
s求和是严格的,这与用于构建列表的(:)
不同。因此,应使用另一种类型
首先,一些导入(我们还需要能够派生数据
,以便可以使用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 <*>)
当然,观察进化可能更有趣:
*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 _) :+ (_ :+ _))))))
好的,如果您将它扩展到
f=fix(\g->\x->Sum x g x)
谢谢,我似乎无法将它原样应用到我的函数中:approxShow 5(f1)
导致没有(Data.Data.Data(Sum Integer))的实例。
。做approxShow 10(getSum(f 1))
也不会终止。@dmedvinsky:对不起,我的错(老实说,我以前从来没有听说过Sum
,认为它是某种自定义类型,所以我没有费心去检查)。答案更新了。hat
和vacuum
都不能帮助我,这很有趣。至少,我找不到一个简单的方法来完成任务,同时保持Integer
s。
f :: S -> Sum S
f = fix ((<>) <$> Sum <*>)
*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 _) :+ (_ :+ _))))))