类型族无法返回 RankN 类型 - 解决方法还是替代方案?



我正在使用可扩展的记录库玩,我想编写一个函数field,该功能可以根据Symbol密钥是否为LensTraversal操作在钥匙列表中。给出了类型的家庭:

type family LensOrTraversal key keys s t a b where
    LensOrTraversal key '[] s t a b = 
        Traversal s t a b
    LensOrTraversal key (key =: val ': xs) s t a b = 
        Lens s t a b
    LensOrTraversal key (foo =: bar ': xs) s t a b = 
        LensOrTraversal key xs s t a b

此代码给我一个错误:

/home/matt/Projects/hash-rekt/src/Data/HashRecord/Internal.hs:433:5: 
error:
    • Illegal polymorphic type: Traversal s t a b
    • In the equations for closed type family ‘LensOrTraversal’
      In the type family declaration for ‘LensOrTraversal’

理想情况下,我希望能够重复使用镜头和遍历的field名称,因为它可以允许您写

>>> let testMap = empty & field @"foo" .~ 'a'
>>> :t testMap
HashRecord '["foo" =: Char]
>>> testMap ^. field @"foo" 
'a'
>>> testMap ^. field @"bar"
Type error
>>> testMap ^? field @"bar"
Nothing

遵循常见的lens成语。我可以提供一个可以执行我想要的fieldTraversal功能,但是如果可能的话,我希望将名称 field超载。您将如何处理这种类型家庭的限制?

lens 已经是遍历,只有其rank2量词不使用完整的约束(它仅需要Functor,而不是Applicative(。

type Lens s t a b      = ∀ f . Functor f     => (a -> f b) -> s -> f t
type Traversal s t a b = ∀ f . Applicative f => (a -> f b) -> s -> f t

您应该介绍您的类型家庭的层面:

import GHC.Exts (Constraint)
type family FieldOpticConstraint key keys :: (* -> *) -> Constraint where
  FieldOpticConstraint key '[] = Applicative
  FieldOpticConstraint key (key =: val ': xs) = Functor
  FieldOpticConstraint key (_ ': xs) = FieldOpticConstraint key xs

field不应产生LensOrTraversal,而应始终具有由类型族确定的约束的自定义rank2-签名。

相关内容

最新更新