haskell - 类型系列无法返回 RankN 类型——解决方法还是替代方案?

标签 haskell types haskell-lens type-families

我正在使用一个可扩展的记录库,并且我想编写一个函数field,它可以作为LensTraversal操作 基于 Symbol 键是否在键列表中。给出了类型族:

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’

理想情况下,我希望能够为镜头和遍历重用字段名称,因为它允许您编写

>>> 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 。您将如何解决类型族的这种限制?

最佳答案

镜头已经是遍历,只是它的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 签名,其约束由类型系列确定。 p>

关于haskell - 类型系列无法返回 RankN 类型——解决方法还是替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43770536/

相关文章:

Python 的新型类的基础—— `object` 和 `type`

c# - 除了 System.Type 之外没有任何更多信息的 Cast 对象

Python:使用字符串作为对象参数?

haskell - 使用镜头应用依赖于多个领域的功能

haskell - 带镜头和 zipper 的遍历树

haskell - 将 Lens 组合成元组的 Lens

haskell - 如何快速检查函数的源代码?

haskell - 干净地替换当前的 Haskell 进程 (exec)

Haskell - getLine 在 putStr 之前调用

haskell - 如何在haskell中获取一元运算符 '-'的类型