{-# LANGUAGE TypeApplications, FlexibleContexts, MultiParamTypeClasses, TemplateHaskell, TypeFamilies, FlexibleInstances #-}
module Main where
import Control.Effect
import Control.Effect.Reader
import Control.Effect.State
import Control.Lens.Wrapped
import Control.Lens.TH
import Test.Hspec
import Control.Effect.Lens
data Context = Context
{ _amount :: Int
, _sweatshirt :: Bool
} deriving (Eq, Show)
initial :: Context
initial = Context 0 False
makeLenses ''Context
stateTest :: (Member (State Context) sig, Carrier sig m, Monad m) => m Int
stateTest = do
initial <- use amount
assign amount (initial + 1)
assign sweatshirt True
use amount
newtype Foo = Foo { _unFoo :: Int } deriving (Eq, Show)
makeWrapped ''Foo
newtype Bar = Bar { _unBar :: Float } deriving (Eq, Show)
makeWrapped ''Bar
doubleStateTest :: (Member (State Bar) sig, Member (State Foo) sig, Carrier sig m, Monad m) => m Int
doubleStateTest = do
assign @Foo _Wrapped 5
assign @Bar _Wrapped 30.5
pure 50
readerTest :: (Member (Reader Context) sig, Carrier sig m, Monad m) => m Int
readerTest = succ <$> view amount
spec :: Spec
spec = describe "use/assign" $ do
it "should modify stateful variables" $ do
let result = run $ runState initial stateTest
result `shouldBe` (Context 1 True, 1)
it "works in the presence of polymorphic lenses with -XTypeAnnotations" $ do
let result = run $ runState (Bar 5) $ runState (Foo 500) doubleStateTest
result `shouldBe` (Bar 30.5, (Foo 5, 50))
it "should read from an environment" $ do
let result = run $ runReader initial readerTest
result `shouldBe` 1
main :: IO ()
main = hspec $ describe "Control.Effect.Lens" spec