packages feed

large-records-0.3: test/Test/Record/Sanity/HKD.hs

{-# LANGUAGE ConstraintKinds           #-}
{-# LANGUAGE DataKinds                 #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE FlexibleInstances         #-}
{-# LANGUAGE KindSignatures            #-}
{-# LANGUAGE MultiParamTypeClasses     #-}
{-# LANGUAGE NamedFieldPuns            #-}
{-# LANGUAGE ScopedTypeVariables       #-}
{-# LANGUAGE TypeApplications          #-}
{-# LANGUAGE TypeFamilies              #-}
{-# LANGUAGE UndecidableInstances      #-}

{-# OPTIONS_GHC -fplugin=Data.Record.Plugin #-}

module Test.Record.Sanity.HKD (
    tests
  ) where

import Data.Functor.Identity
import Data.Functor.Const
import Data.Kind
import GHC.Records.Compat

import Test.Tasty
import Test.Tasty.HUnit

type family HKD f a where
  HKD Identity  a = a
  HKD (Const b) a = b

-- | Test record with fields whose types are given by type families
{-# ANN type T largeRecord #-}
data T (f :: Type -> Type) = MkT {
      field1 :: HKD f Int
    , field2 :: HKD f Bool
    }
  deriving (Show, Eq)

{-------------------------------------------------------------------------------
  Tests
-------------------------------------------------------------------------------}

tests :: TestTree
tests = testGroup "Test.Record.Sanity.HKD" [
      testCase "get"   testGet
    , testCase "set"   testSet
    , testCase "match" testMatch
    ]

example1, example2 :: T Identity
example1 = MkT { field1 = 1, field2 = True  }
example2 = MkT { field1 = 1, field2 = False }

example3 :: T (Const Char)
example3 = MkT { field1 = 'a', field2 = 'b' }

exampleFun :: T f -> HKD f Int
exampleFun MkT { field1 } = field1

testGet, testSet :: Assertion
testGet = assertEqual "" (getField @"field1" example1) 1
testSet = assertEqual "" (setField @"field2" example2 False) example2

testMatch :: Assertion
testMatch = do
    assertEqual "example1" (exampleFun example1) 1
    assertEqual "example3" (exampleFun example3) 'a'