content: {-# LANGUAGE TemplateHaskell #-}
  {-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}
  
  module MultipleVarsSpec where
  
  import Polysemy
  import Polysemy.State
  
  import Test.Hspec
  
  data TaggedState k s m a where
    TaggedGet :: forall k s m. TaggedState k s m s
    TaggedPut :: forall k s m. s -> TaggedState k s m ()
  
  makeSem ''TaggedState
  
  runTaggedState :: forall k s r a
                  . s
                 -> Sem (TaggedState k s ': r) a
                 -> Sem r (s, a)
  runTaggedState s =
      (runState s .)
    $ reinterpret
    $ \case
      TaggedGet -> get
      TaggedPut s -> put s
  
  test :: Members '[
            TaggedState Char Int
          , TaggedState Bool Int
          ] r
       => Sem r ()
  test = do
    taggedPut @Bool 10
    taggedPut @Char (-10)
  
  spec :: Spec
  spec = describe "Using multiple, but ununifiable instances\
                 \ of the same effect" $ do
    it "should get disambiguated and compile, \
       \and actions should target the right effects." $ do
      let
        res1 =
            run
          . runTaggedState @Char 0
          . runTaggedState @Bool 7
          $ test
        res2 =
            run
          . runTaggedState @Bool 0
          . runTaggedState @Char 7
          $ test
        res3 =
            run
          . runTaggedState @Bool 0
          . runTaggedState @Char 7
          $ do
            taggedPut @Bool 10
            taggedPut @Char (-10)
      res1 `shouldBe` (-10, (10, ()))
      res2 `shouldBe` (10, (-10, ()))
      res3 `shouldBe` (10, (-10, ()))
  