packages feed

fcf-containers-0.8.2: test/Test/Alg/Tree.hs

{-# LANGUAGE ScopedTypeVariables    #-}
{-# LANGUAGE TypeApplications       #-}
{-# LANGUAGE TypeFamilies           #-}
{-# LANGUAGE TypeInType             #-}
{-# LANGUAGE TypeOperators          #-}
{-# LANGUAGE UndecidableInstances   #-}
{-# OPTIONS_GHC -Wall                       #-}
{-# OPTIONS_GHC -Werror=incomplete-patterns #-}

{- 
In this module, we test mainly Fcf.Alg.Tree module. In couple of 
places, we use the "spec" and Reflect. 

Many of the tests are such that if the answer is not correct, the
whole test module refuses to compile.  Please do try to change some 
of the values to see. 

Note that in a way, the spec tests are not needed. If testing just 
the type level behaviour, the module would refuse to compile if 
test is not ok (and thus, guard the quality earlier than what the 
test framework can do).  

Anyhow, as these also work as examples, it is probably ok to have different 
ways of reaching the results. (E.g. to see, how to get the type level 
values to value level.)

-}

module Test.Alg.Tree where

import qualified GHC.TypeLits as TL

import           Data.Proxy
import           Data.Type.Equality ((:~:)(Refl))
import           Test.Hspec (describe, it, shouldBe, Spec)

import           Fcf.Data.Nat

import           Fcf.Alg.Morphism 
import           Fcf.Alg.Tree
import           Fcf.Combinators (type (=<<))
import           Fcf.Core (Eval, Exp)
import           Fcf.Utils (If)
import           Fcf.Data.Reflect (fromType)
import           Fcf.Data.Tree

data BuildNode :: Nat -> Exp (Nat,[Nat])
type instance Eval (BuildNode x) =
    If (Eval ((2 TL.* x TL.+ 1) >= 8))
        '(x, '[])
        '(x, '[ 2 TL.* x, (2 TL.* x) TL.+ 1 ])

-- > :kind! Eval (Size =<< UnfoldTree BuildNode 1)
-- Eval (Size =<< UnfoldTree BuildNode 1) :: TL.Natural
-- = 7
_ = Refl :: Eval (Size =<< UnfoldTree BuildNode 1) :~: 7


-- :kind! Eval (Ana BuildNodeCoA 1)
-- :kind! Eval (Hylo CountNodesAlg BuildNodeCoA 1)


-- > :kind! Eval (Sizes =<< Ana BuildNodeCoA 1)
-- Eval (Sizes =<< Ana BuildNodeCoA 1) :: Fix
--                                          (AnnF (TreeF TL.Natural) TL.Natural)
-- = 'Fix
--     ('AnnF
--        '( 'NodeF
--             1
--             '[ 'Fix
--                  ('AnnF
--                     '( 'NodeF
--                          2
--                          '[ 'Fix ('AnnF '( 'NodeF 4 '[], 1)),
--                             'Fix ('AnnF '( 'NodeF 5 '[], 1))],
--                        3)),
--                'Fix
--                  ('AnnF
--                     '( 'NodeF
--                          3
--                          '[ 'Fix ('AnnF '( 'NodeF 6 '[], 1)),
--                             'Fix ('AnnF '( 'NodeF 7 '[], 1))],
--                        3))],
--           7))
_ = Refl :: Eval (Sizes =<< Ana BuildNodeCoA 1)
  :~: 'Fix
    ('AnnF
       '( 'NodeF
            1
            '[ 'Fix
                 ('AnnF
                    '( 'NodeF
                         2
                         '[ 'Fix ('AnnF '( 'NodeF 4 '[], 1)),
                            'Fix ('AnnF '( 'NodeF 5 '[], 1))],
                       3)),
               'Fix
                 ('AnnF
                    '( 'NodeF
                         3
                         '[ 'Fix ('AnnF '( 'NodeF 6 '[], 1)),
                            'Fix ('AnnF '( 'NodeF 7 '[], 1))],
                       3))],
          7))

-- Turning this off, because of the slowness. In practice, this would
-- also require turning on ghc-options (-freduction-depth=0). 
-- Please, do try on ghci.
-- > :kind! Eval (FibHisto 100)
-- Eval (FibHisto 100) :: TL.Natural
-- = 354224848179261915075
-- _ = Refl :: Eval (FibHisto 100) :~: 354224848179261915075

-- > :kind! Eval (FibHylo 10)
-- Eval (FibHylo 10) :: TL.Natural
-- = 55
spec :: Spec
spec = describe "Tree" $ do
  it "FibHisto" $ do
    let test :: forall r. (r ~ Eval (FibHylo 10)) => Int
        test = fromType (Proxy @r)
    test `shouldBe` 55
  -- The following is very slow and would require turning on ghc-options
  -- (-freduction-depth=0).  
  -- it "FibHisto" $ do
  --   let test :: forall r. (r ~ Eval (FibHisto 100)) => Integer
  --       test = fromType (Proxy @r)
  --   test `shouldBe` 354224848179261915075