GameState = GameState {...}
makeClassy ''GameState
update:: (MonadState s m, HasGameState s) => m ()
I believe this is how peole use the lens library with mtl style. Now what if my GameState takes a type varible, like in GameState a. How should I call makeClassy in this case?
So far, I've managed to do it without the type variable:
data Heap = forall a. Show a => Heap { _hpLength :: Int
, _hpSize :: Int
, _hpObjs :: Seq a }
instance Show Heap where
show (Heap l s o) = show l ++ show s ++ show (toList o)
makeClassy ''Heap
hpInsert :: (MonadIO m, MonadState s m, HasHeap s) => a -> m s
hpInsert e = do
hpSize += 1
s <- get
return s
test :: IO Heap
test = evalStateT (hpInsert 1) ( Heap 1 1 (fromList [1..9]))
It compiles and seems to work but I feel something is not quite the same between:
data Heap =...
and
data Heap a
Note1:
Just realize that after makeClassy, I don't get a lens hpObjs. How should I access that field then?
Note2:
I got it working with the following modification. I still would like to understand how to better use makeClassy though.
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TemplateHaskell #-}
module Algo.Heap
(
Heap
, test
) where
import Control.Lens hiding (element)
import Control.Lens.TH
import Control.Monad.State.Lazy
import Data.Foldable (toList)
import Data.Sequence hiding ((<|))
data Heap a = Heap { _hpLength :: Int
, _hpSize :: Int
, _hpObjs :: Seq a }
instance Show a => Show (Heap a) where
show (Heap l s o) = show l ++ show s ++ show (toList o)
makeLenses ''Heap
hpInsert :: (MonadIO m, MonadState (Heap a) m) => a -> m ()
hpInsert e = do
hpSize += 1
hpObjs %= (e <|)
test :: IO ()
test = execStateT (hpInsert 1) ( Heap 1 1 (fromList [1..9]))
>>= execStateT (hpInsert 2)
>>= print