How to makeClassy a type with a type variable in the lens library

Viewed 58
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
0 Answers
Related