{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wno-orphans #-} -- | Tests for the polytropos-lens satellite. The plugin solves the -- FieldIndex, ConstructorIndex, RowEq/RowShow and RowEqSum/RowShowSum -- constraints below as literals. module Main (main) where import Test.Tasty import Test.Tasty.HUnit import Control.Lens ((&), (.~), (^.), (^..), (^?), (%~), at, each, ix, preview, review, (?~), _1, _2, _3) import Polytropos import Polytropos.Lens type MyRec = Record '["x" ':= Int, "y" ':= Bool, "z" ':= Bool] type HomRec = Record '["x" ':= Int, "y" ':= Int, "z" ':= Int] type MyVar = Variant '["A" ':= '["foo" ':= Int], "B" ':= '["bar" ':= Bool]] myRec :: MyRec myRec = REC { x = 42, y = True, z = False } homRec :: HomRec homRec = REC { x = 1, y = 2, z = 3 } varA :: MyVar varA = Variant (Field @"A") (REC { foo = 42 :: Int }) varB :: MyVar varB = Variant (Field @"B") (REC { bar = False }) main :: IO () main = defaultMain $ testGroup "Lens Integration" [ testGroup "positional lenses" [ testCase "view _1, _2, _3" $ do (myRec ^. _1) @?= (42 :: Int) (myRec ^. _2) @?= True (myRec ^. _3) @?= False , testCase "set _1" $ do let r' = myRec & _1 .~ (100 :: Int) (r' ^. _1) @?= (100 :: Int) (r' ^. _2) @?= True , testCase "over _2" $ ((myRec & _2 %~ not) ^. _2) @?= False ] , testGroup "each" [ testCase "modifies all fields" $ (homRec & each %~ (+ (1 :: Int))) @?= (insertField (Field @"x") (2 :: Int) $ insertField (Field @"y") (3 :: Int) $ insertField (Field @"z") (4 :: Int) $ emptyRecord) , testCase "views all fields" $ (homRec ^.. each) @?= [1 :: Int, 2, 3] ] , testGroup "At and Ixed" [ testCase "ix views by name" $ do (homRec ^? ix "x") @?= (Just (1 :: Int)) (homRec ^? ix "z") @?= (Just (3 :: Int)) (homRec ^? ix "nope") @?= (Nothing :: Maybe Int) , testCase "at views by name" $ do (homRec ^. at "y") @?= (Just (2 :: Int)) (homRec ^. at "nope") @?= (Nothing :: Maybe Int) , testCase "at sets existing field" $ do let r' = homRec & at "y" ?~ (9 :: Int) (r' ^. at "y") @?= (Just (9 :: Int)) (r' ^. at "x") @?= (Just (1 :: Int)) , testCase "ix sets existing field" $ do let r' = homRec & ix "z" .~ (7 :: Int) (r' ^? ix "z") @?= (Just (7 :: Int)) ] , testGroup "fieldLens" [ testCase "views by field name" $ do (myRec ^. fieldLens #x) @?= (42 :: Int) (myRec ^. fieldLens #z) @?= False , testCase "sets by field name" $ ((myRec & fieldLens #x .~ (7 :: Int)) ^. fieldLens #x) @?= (7 :: Int) ] , testGroup "variant prisms" [ testCase "prism matches A" $ do preview (prismVariant (Field @"A")) varA @?= Just (insertField (Field @"foo") (42 :: Int) emptyRecord) preview (prismVariant (Field @"A")) varB @?= (Nothing :: Maybe (Record '["foo" ':= Int])) , testCase "prism matches B" $ preview (prismVariant (Field @"B")) varB @?= Just (insertField (Field @"bar") False emptyRecord) , testCase "prism inject roundtrip" $ review (prismVariant (Field @"A")) (insertField (Field @"foo") (42 :: Int) emptyRecord) @?= varA ] ]