2013-07-09 10 views
8

SceneGraphタイプのフィールド '_scene'を持つレコードで、以下のコードを使用しています。私はmakeLensesを使ってレンズを作りました。このレンズを使用するには、私のデータ型がMonoidのインスタンスに必要なのはなぜですか?

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 

をしかし、シーングラフは、このレンズを使用するために、モノイドのインスタンスである必要があり、なぜ私は理解していません。

答えて

14

をインポートすることを賭けている:> R

編集 - > SRを折ります。

あなたがLens(またはGetterIsoEqualityなど)を持っている場合、それは常に1つのアイテムを指します。したがって、普通の古い(^.)(非演算子名:view)を使用することができます。 Traversal(またはFold,Prismなど)がある場合、0以上のアイテムを参照できます。

したがって、複数ある場合はそれらを組み合わせる方法があり、存在しない場合はデフォルト値を指定する必要があります。これはMonoidの制約で行われます。 toListOfには、すべての値の一覧が表示されます。 previewNothingまたはJustのいずれかを最初の値にします。

あなたが使用している機能のタイプを指定していないため、意図したことを本当に分かりません。私が推測するのは、makeLensesをsum sumにすべてsceneを定義しない合計型で使用したため、sceneが失敗する可能性があります。この場合は、おそらく(^?)を使用し、Nothingケースを処理することをお勧めします。しかし、それは別のものかもしれません。

私の答えはthis question(また昨日のthis question!これは人気のあるトピックのようです)も参照してください。

+0

ああ!だから、 'makeLenses'がプリズムを作り出す理由です。 –

+1

さて、私はそれを得ると思います。私のデータ型がデータのように見えるからです。Game = GameLoad |ゲーム{_scene :: SceneGraph} | GameOverので、ゲームが他の2つのコンストラクタの1つであるために 'scene'が失敗する可能性があります。 – schellsan

+0

Aha。はい。あなたは 'GameLoad' /' GameOver'のケースを扱う必要があります。 – shachaf

1

私はあなたがEd Kmettのレンズライブラリを使用していると仮定しています。使用しているバージョンとインポートを投稿することができれば助かります。また、そのレンズライブラリでサポートされている2つのバージョン(^。)があるように見えます。一つはGetter、もう一つはFold、foldはMonoidのインスタンスを必要とします:(^。):: Monoid r => s - 私はあなたがおそらく(^?)、または多分(^..)(:previewtoListOf非オペレータ名)のいずれか欲しいあなたが誤ってControl.Lens.Fold

+3

いいえ、 '(^。)は1つだけです。フォールド/トラバーサルを使用すると、 'Monoid'制約が追加されます。 – shachaf

+0

結果がMonoidであることを要求する利点は何ですか? – schellsan

+2

レンズが実際に0( 'mempty')または複数(' mconcat')の値にフォーカスされている場合でも、1つの結果が返されます。 –

関連する問題