packages feed

generic-lens-0.4.0.1: test/Spec.hs

{-# OPTIONS_GHC -O -fplugin GHC.Proof.Plugin #-}

{-# LANGUAGE AllowAmbiguousTypes             #-}
{-# LANGUAGE DataKinds                       #-}
{-# LANGUAGE DeriveGeneric                   #-}
{-# LANGUAGE DuplicateRecordFields           #-}
{-# LANGUAGE ExistentialQuantification       #-}
{-# LANGUAGE RankNTypes                      #-}
{-# LANGUAGE ScopedTypeVariables             #-}
{-# LANGUAGE TypeApplications                #-}

module Main where

import GHC.Generics
import Data.Generics.Product
import GHC.Proof

main :: IO ()
main = putStrLn "Hello world"

data Record = MkRecord
  { fieldA :: Int
  , fieldB :: Bool
  } deriving Generic

data Record2 = MkRecord2
  { fieldA :: Int
  } deriving Generic

type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s

fieldALensManual :: Lens' Record Int
fieldALensManual f (MkRecord a b) = (\a' -> MkRecord a' b) <$> f a

newtype L s a = L (Lens' s a)

subtypeLensManual :: Lens' Record Record2
subtypeLensManual f record
  = fmap (\ds -> case record of
                  MkRecord _ b -> MkRecord (case ds of {MkRecord2 g1 -> g1}) b
         ) (f (MkRecord2 (case record of {MkRecord a _ -> a})))

--------------------------------------------------------------------------------
-- * Tests
-- The ghc-proofs plugin checks that the following equalities hold, by checking
-- that the LHSs and the RHSs are CSEd. This also means that the runtime
-- characteristics of the derived lenses is the same as the manually written
-- ones above.

fieldP :: Proof
fieldP = L fieldALensManual === L (field @"fieldA")

typedP :: Proof
typedP = L fieldALensManual === L (typed @Int)

posP :: Proof
posP = L fieldALensManual === L (position @1)

subtypeP :: Proof
subtypeP = L subtypeLensManual === L super