Inspired by this two comments on reddit I set out to create a 'lensified entity system'. The basic idea is to have Lens' Entity Value
lenses, but although there is Action
to create Getter
s with side effects there is no Setter
or a combined LensM'
-thing.
I could probably use something like Lens' (Entity, State) Value
but I would be interested in how (and if) this could be done in a better way.
Ok ... here is what I got:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import qualified Data.Map as M
import Control.Monad.State
import Control.Lens
newtype Entity = Entity { unEntity :: Int }
deriving (Show, Eq, Ord, Enum)
type Address = String
type Name = String
data EntitySystem = EntitySystem {
_nextEntity :: Entity,
_addresses :: M.Map Entity Address,
_names :: M.Map Entity Name
} deriving (Show, Eq, Ord)
makeLenses ''EntitySystem
newEntry :: Name -> Address -> State EntitySystem Entity
newEntry name addr = do
ne <- nextEntity <<%= succ
addresses.at ne ?= addr
names.at ne ?= name
return ne
entityAddress e = addresses . at e
entityName e = names . at e
Basically I can use entityAddress entity
(which should be of type Entity -> Lens' EntitySystem Address
but ghc is complaining). But this doesn't feel 'lensy'. What I am hoping for is something like entityAddress :: Lens' Entity Address
where all the stateful handling of the entity system is hidden from the user.