镜头包:TH派生实例,用于保存派生数据类型的数据类型

时间:2018-05-23 19:07:14

标签: haskell lens template-haskell

我有以下内容:

data Dog =
  Dog
  { _x :: Int
  }
makeFieldsNoPrefix ''Dog

data Cat =
  Cat
  { _dog :: Dog
  }
makeFieldsNoPrefix ''Cat

这为我提供了HasXHasDog类以及实例instance HasDog Cat Doginstance HasX Dog Int

但我还想生成instance HasX Cat Int,这个TH功能是否可以在某处使用?

1 个答案:

答案 0 :(得分:1)

至少有两个很好的理由makeFields不会为传递包含的字段生成Has个实例。

  1. 在由许多数据类型组成的大型结构中,为结构中某处包含的每个字段生成Has个实例会很慢(O(n ^ 2))。
  2. 选择x并不总是显而易见的选择。考虑

    data TwoDogs = { _dog1 :: Dog, _dog2 :: Dog }
    

    Dog _x TwoDogs HasX Lens镜头访问权限?它是Traversal,而不是HasX,因此您必须选择一个。期望自动化工具为您做出决定是不合理的。

  3. 幸运的是镜头非常容易构图。如果您希望您的类型具有_x实例,该实例标识嵌套在结构中的特定instance HasX Cat Int where x = dog.x (根据某些特定于域的规则),您只需编写一个。

    Class<?> cls = ClassB.class;
    Object obj = cls.newInstance();
    (ClassB)obj.setA(); 
    (ClassB)obj.test();