Что порождает нерешенные ограничения типа в этом приложении универсального объектива? - PullRequest
2 голосов
/ 27 сентября 2019

У меня есть следующий модуль, основанный на примерах из 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
   |                                       ^^^^^^^^^^^^

Я могу напрямую использовать реализацию field Хиггедли в той же кодовой базе, как:

sxLabels :: Labels SxRecord
sxLabels = textLabel @SxRecord

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

Так почему же это не работает в первом случае?Есть ли исправление?

1 Ответ

3 голосов
/ 28 сентября 2019

Ваша подпись запрашивает HasField' на HKD structure f (для некоторого неизвестного f), но вы на самом деле пытаетесь использовать field' на HKD structure (Const Text).Отсюда ошибка «отсутствует экземпляр».

Вам нужно заменить 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
...