パッケージChasingBottoms
は、approxShow
部分的に評価された値を調べるのに役立ちます:
$ 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 の合計Integer
はstrictです。(:)
したがって、別のタイプを使用する必要があります。
最初に、いくつかのインポート (カスタム型を表示するために使用できるように、派生できるようにする必要もあります) 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 _) :+ (_ :+ _))))))