Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would my datatype need to an instance of Monoid to use this lens?

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.

like image 583
schellsan Avatar asked Jul 09 '13 01:07

schellsan


1 Answers

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).

like image 91
shachaf Avatar answered Nov 16 '22 04:11

shachaf