类型系列不能返回RankN类型 - 变通办法或替代方案?

时间:2017-05-03 21:47:11

标签: haskell types lens type-families

我正在玩一个可扩展的记录库,我想编写一个函数field,它可以作为LensTraversal运行,具体取决于是否Symboltype 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习语。我可以提供{ entry: { app: './app.js', concatenated: ['es5-shim', 'es5-shim/es5-sham', 'es6-shim', './vendor/polyfills.js'] }, output: { filename: '[name].js' } 函数来执行我想要的操作,但如果可能的话,我更愿意重载名称[c_name, c.pi for (c_name, c) in prob.constraints.items()] 。你会如何解决这类家庭的限制?

1 个答案:

答案 0 :(得分:4)

镜头 已经是遍历,只有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签名。