是什么导致了这种通用镜头应用中未解决的类型约束?



我有以下模块,基于higgledy README的示例及其源代码。

{-# LANGUAGE AllowAmbiguousTypes       #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE KindSignatures            #-}
{-# LANGUAGE ScopedTypeVariables       #-}
{-# LANGUAGE TypeApplications          #-}

module FDS.UtilTypes where
import           Control.Lens                     ((^.), Const (..))
import qualified Data.Generics.Internal.VL.Lens   as G
import qualified Data.Generics.Product            as G
import           Data.Functor.Const               (Const (..))
import           Data.Generic.HKD
import           Data.Kind (Type)
type Labels a = HKD a (Const Text) -- Every field holds a string.
class TextLabel (structure :: Type) where
textLabel :: HKD structure (Const Text)
getLabel :: forall ft f structure inner.
G.HasField' ft (HKD structure f) (f inner) =>
Labels structure -> Text
getLabel labels = getConst $ labels ^. G.field' @ft

似乎我已经忠实地再现了他们在getLabel签名的第一部分的field价值,但仍然有些不对劲:

• Could not deduce: Data.Generics.Product.Fields.ErrorUnless
ft
(HKD structure (Const Text))
(generic-lens-1.1.0.0:Data.Generics.Internal.Families.Collect.CollectField                                                                              
ft (GHKD_ (Const Text) (GHC.Generics.Rep structure)))
arising from a use of ‘G.field'’
from the context: G.HasField' ft (HKD structure f) (f inner)
bound by the type signature for:
getLabel :: forall (ft :: ghc-prim-0.5.3:GHC.Types.Symbol) (f :: *
             -> *) structure inner.                                                                         
G.HasField' ft (HKD structure f) (f inner) =>
Labels structure -> Text
at src/FDS/UtilTypes.hs:(45,1)-(47,26)
• In the second argument of ‘(^.)’, namely ‘G.field' @ft’
In the second argument of ‘($)’, namely ‘labels ^. G.field' @ft’
In the expression: getConst $ labels ^. G.field' @ft
• Relevant bindings include
labels :: Labels structure (bound at src/FDS/UtilTypes.hs:48:9)
getLabel :: Labels structure -> Text
(bound at src/FDS/UtilTypes.hs:48:1)
|
48 | getLabel labels = getConst $ labels ^. G.field' @ft
|                                       ^^^^^^^^^^^^
• Could not deduce (Data.Functor.Contravariant.Contravariant
(GHKD_ (Const Text) (GHC.Generics.Rep structure)))
arising from a use of ‘G.field'’
from the context: G.HasField' ft (HKD structure f) (f inner)
bound by the type signature for:
getLabel :: forall (ft :: ghc-prim-0.5.3:GHC.Types.Symbol) (f :: *
             -> *) structure inner.                                                                         
G.HasField' ft (HKD structure f) (f inner) =>
Labels structure -> Text
at src/FDS/UtilTypes.hs:(45,1)-(47,26)
• In the second argument of ‘(^.)’, namely ‘G.field' @ft’
In the second argument of ‘($)’, namely ‘labels ^. G.field' @ft’
In the expression: getConst $ labels ^. G.field' @ft
|
48 | getLabel labels = getConst $ labels ^. G.field' @ft
|                                       ^^^^^^^^^^^^

我可以直接在同一个代码库中使用 higgledy 的field实现,例如:

sxLabels :: Labels SxRecord
sxLabels = textLabel @SxRecord
markKey :: Text
markKey = getConst $ sxLabels ^. field @"mark"

那么为什么这在第一种情况下不起作用呢?有修复吗?

您的签名要求HKD structure fHasField'(对于某些未知f(,但您实际上是在尝试在HKD structure (Const Text)上使用field'。因此,"缺少实例"错误。

您需要将约束中的f替换为Const Text并摆脱f

getLabel :: forall ft structure inner.
G.HasField' ft (HKD structure (Const Text)) (Const Text inner) =>
Labels structure -> Text
getLabel labels = getConst $ labels ^. G.field' @ft

最新更新