簡體   English   中英

為什么我的數據類型需要使用Monoid的實例來使用這個鏡頭?

[英]Why would my datatype need to an instance of Monoid to use this 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

我收到錯誤:

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

但我不明白為什么SceneGraph必須是Monoid的一個實例才能使用這個鏡頭。

您可能想要(^?)或者(^..) (非運算符名稱: previewtoListOf )。

當你有一個Lens (或一個GetterIsoEquality等)時,它總是指一個項目。 所以你可以使用普通舊(^.) (非運營商名稱: view )。 當您有Traversal (或FoldPrism等)時,它可以引用0或更多項目。

因此,如果存在多個,則必須有一種方法來組合它們,如果沒有,則必須提供默認值。 這是通過Monoid約束完成的。 toListOf為您提供所有值的列表; preview為您提供NothingJust the first值。

您沒有為您正在使用的任何功能提供類型,因此我無法確切地說出您的意圖。 我的猜測可能是scene可能會失敗,因為你使用的makeLenses的sum類型並沒有在每個makeLenses中定義scene 在這種情況下,您可能想要使用(^?)並處理Nothing案例。 但它可能是別的東西。

另見我對這個問題的回答 (以及昨天的這個問題 !這似乎是一個熱門話題)。

我假設您正在使用Ed Kmett的鏡頭庫,如果您還可以發布您正在使用的版本和導入,那將會很有幫助。 它看起來在該鏡頭庫中支持兩個版本的(^。),一個帶有Getter,另一個帶有Fold,需要Monoid實例的折疊版本:(^。):: Monoid r => s - >折疊sr - > r

編輯:我打賭你不小心導入了Control.Lens.Fold

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM