使用Control.Lens的索引列表需要Monoid约束

时间:2013-07-08 02:12:10

标签: haskell lenses lens

以下代码无法编译:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data MyType = MyType Int
data Outer = Outer { _inners :: [ Inner ] }
data Inner = Inner { _val :: MyType }

$(makeLenses ''Outer)
$(makeLenses ''Inner)

i1 = Inner (MyType 1)
i2 = Inner (MyType 2)

o = Outer [i1, i2]

x = o ^. inners . ix 0 . val

发出此错误

Toy.hs:17:23:
No instance for (Data.Monoid.Monoid MyType)
  arising from a use of `ix'
Possible fix:
  add an instance declaration for (Data.Monoid.Monoid MyType)
In the first argument of `(.)', namely `ix 0'
In the second argument of `(.)', namely `ix 0 . val'
In the second argument of `(^.)', namely `inners . ix 0 . val'

假设MyType成为一个幺半群是没有意义的,我怎样才能获得允许我访问此嵌套的镜头(或遍历,或任何最合适的东西 - 我不确定区别)领域?最好能够同时阅读和更新。

1 个答案:

答案 0 :(得分:9)

因为ix n可能失败(例如:n >= length list),您需要一种干净的失败方法。选择的干净失败是来自mempty的{​​{1}}元素。因此,立即出现的问题是,如果您的类型不能是Monoid,那么您希望此代码如何失败?

我建议您使用Monoid代替^?,从而重复使用名为^.的{​​{1}}:

Monoid