I’m trying to write a game in haskell and i’d like to write it in a modular way. To simplify it, I have a GameState
and functions that do GameState -> GameState
.
type Dog = Int
data GameState = GameState {
cat :: String,
extensionState :: ExtState
}
data ExtState = ExtState {
dogExt :: Dog
}
type ExtEffects = [GameState -> GameState]
-- (we can partially apply the lens so it becomes `GameState -> `GameState`
type StatefulEffect s = Lens' GameState s -> GameState -> GameState
doDog :: StatefulEffect Dog
doDog l gs = over l (+1) gs
-- maybe you could define the extension as something similar to this?
data Extension s = Extension {
extState :: s,
extEffect :: StatefulEffect s
}
In this example, the only thing that needs to access the Dog
in ExtState
is doDog
. So doDog
is essentially like an extension that has its own state which is stored in GameState
. (In a real implementation, doDog
would also act on parts of the GameState
that are known by everyone).
It’s workable like this, but I’d like to be able to do this without having to define each field manually in State
, and adding the function to ExtEffects
and giving it the lens (not shown here). Ideally, I could pass the enabled extensions into some sort of list (at compile time) and it would magically work out. The state also doesn’t need to be stored as a field; anything works as long it’s accessible by a lens on GameState
.
I’ve tried using the extensible
library to add rows to the record with row-polymorphism. It works, but it’s just as much boilerplate as this pretty much. The lenses are the issue, since they all need to know the type of ExtState
. And even if I got those to work, I have no idea how to reduce the boilerplate so you only need to ‘enable’ an extension in one place.
hello is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.