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).
I'm assuming you are using Ed Kmett's lens library, it would be helpful if you could also post the version you are using and the imports. It also looks like there are two versions of (^.) supported in that lens library, one with a Getter and one with a Fold, the fold version requiring an instance of Monoid: (^.) :: Monoid r => s -> Fold sr -> r
Edit: I'm betting that you accidentally imported Control.Lens.Fold
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.