I'm using the code below on a record that has a field '_scene' of type SceneGraph. I've created lenses for it using makeLenses.
inputGame :: Input -> Game -> Game
inputGame i g = flip execState g $ do
let es = g ^. userInput . events
sg = g ^. scene
userInput .= i
scene .= foldl (flip inputEvent) sg es
inputEvent :: InputEvent -> SceneGraph -> SceneGraph
inputEvent (WindowSizeChangedTo (w,h)) (SceneRoot _ _ sg) = SceneRoot w h sg
inputEvent _ sg = sg
I'm getting the error:
No instance for (Monoid SceneGraph) arising from a use of `scene'
Possible fix: add an instance declaration for (Monoid SceneGraph)
In the second argument of `(^.)', namely `scene'
In the expression: g ^. scene
In an equation for `sg': sg = g ^. scene
But I don't understand why SceneGraph has to be an instance of Monoid in order to use this lens.
You probably want either (^?)
, or maybe (^..)
(non-operator names: preview
, toListOf
).
When you have a Lens
(or a Getter
, Iso
, Equality
, etc.), it always refers to exactly one item. So you can use plain old (^.)
(non-operator name: view
). When you have have a Traversal
(or a Fold
, Prism
, etc.), it can refer to 0-or-more items.
Therefore there must be a way to combine them if there's more than one, or a default value to give if there are none. This is done with the Monoid
constraint. toListOf
gives you a list of all the values; preview
gives you either Nothing
or Just
the first value.
You didn't give the types for any of the functions you're using, so I can't really tell what you intended. My guess would be that maybe scene
can fail because you used makeLenses
with a sum type that doesn't define scene
in every summand. In this case you'd probably want to use (^?)
and handle the Nothing
case. But it might be something else.
See also my answer to this question (and this question from yesterday! This seems to be a popular topic).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With