1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-
Example adapted from SYB
========================
-}
module Main (main) where
import Control.Lens
import Control.Monad (void)
import Data.Generics.Product
import GHC.Generics
import Test.HUnit
main :: IO ()
main = void $ runTestTT tests
-- A parameterised datatype for binary trees with data at the leafs
data Tree a w = Leaf a
| Fork (Tree a w) (Tree a w)
| WithWeight (Tree a w) w
deriving (Show, Generic, Eq)
-- A typical tree
mytree :: Tree Int Int
mytree = Fork (WithWeight (Leaf 42) 1)
(WithWeight (Fork (Leaf 88) (Leaf 37)) 2)
mytreeShown :: Tree String Int
mytreeShown = Fork (WithWeight (Leaf "42") 1)
(WithWeight (Fork (Leaf "88") (Leaf "37")) 2)
-- A polymorphic-recursive structure
data Poly a b
= PNil
| PCons a (Poly b a)
deriving (Show, Generic)
poly :: Poly Int String
poly = PCons 10 (PCons "hello" (PCons 20 (PCons "world" PNil)))
-- Print everything like an Int in mytree
-- In fact, we show two attempts:
-- 1. print really just everything like an Int
-- 2. print everything wrapped with Leaf
-- So (1.) confuses leafs and weights whereas (2.) does not.
tests :: Test
tests = TestList
[ toListOf (types @Int) mytree ~=? [42,1,88,37,2]
, toListOf (param @1) mytree ~=? [42,88,37]
-- Things not (easily) doable in SYB:
-- change type of Tree by mapping a function over the second (from the right) param
, (mytree & param @1 %~ show) ~=? mytreeShown
-- collect values in poly corresponding to the first param
, toListOf (param @0) poly ~=? ["hello", "world"]
-- collect all Ints inside poly
, toListOf (types @Int) poly ~=? [10, 20]
-- map length over the Strings, then collect all Ints
, toListOf (types @Int) (poly & param @0 %~ length) ~=? [10, 5, 20, 5]
-- map length over the Strings, then collect all the resulting Ints
, toListOf (param @0) (poly & param @0 %~ length) ~=? [5,5]
]
-- original code from SYB:
--tests = show ( listify (\(_::Int) -> True) mytree
-- , everything (++) ([] `mkQ` fromLeaf) mytree
-- ) ~=? output
-- where
-- fromLeaf :: Tree Int Int -> [Int]
-- fromLeaf (Leaf x) = [x]
-- fromLeaf _ = []
|