sch*_*san 9 haskell monoids lenses haskell-lens
我在具有SceneGraph类型字段'_scene'的记录上使用下面的代码.我用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
Run Code Online (Sandbox Code Playgroud)
我收到错误:
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
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么SceneGraph必须是Monoid的一个实例才能使用这个镜头.
sha*_*haf 16
你可能想要么(^?),也许(^..)(非运营商名称:preview,toListOf).
当你有一个Lens(或一Getter,Iso,Equality,等),它通常是指只有一个项目.所以你可以使用普通的旧(^.)(非运营商名称:) view.当你有一个Traversal(或一个Fold,Prism等等),它可以引用0或更多的项目.
因此,如果存在多个,则必须有一种方法来组合它们,如果没有,则必须提供默认值.这是通过Monoid约束完成的.toListOf为您提供所有值的列表; preview给你Nothing或者Just第一个值.
您没有为您正在使用的任何功能提供类型,因此我无法确切地说出您的意图.我的猜测可能scene会失败,因为你使用makeLenses了没有scene在每个summand中定义的和类型.在这种情况下,您可能想要使用(^?)和处理Nothing案例.但它可能是别的东西.
另见我对这个问题的回答(以及昨天的这个问题!这似乎是一个热门话题).