Не удалось сделать вывод (показать a10), возникающий из-за использования «def»

Я застрял на этой ошибке довольно долгое время. Я не уверен, что я глуп, но я не могу понять, откуда это исходит...

Тип данных Settings определяется так:

data Settings a = Settings { 
         _nodeDrawFunction :: a -> Diagram B
       , _dynamicHead :: Measure Double
       , _dynamicThick :: Measure Double
       , _directed :: Directed
       , _horizontalOrientation :: Maybe Bool
       , _layerSpacing :: Maybe Double
       , _nodeSpacing :: Maybe Double
       , _graphPadding :: Maybe Double
       , _colF :: Maybe (Int -> Colour Double)
       , _bgOp :: Maybe Double
       , _initPos :: Maybe Int
      }

А makeLenses ''Settings используется для создания линз для каждой записи. По умолчанию для _drawNodeFunction используется drawDefaultNode.

Когда я создаю функцию, перезаписывающую некоторые из этих значений, используя сеттеры Lens, она работает нормально, например:

test1 :: (Show a) => Graph a -> Settings a
test1 g = def & bgOp .~ Just 1

Что работает, как ожидалось. Тип Graph взят из библиотеки алгебраических графов.

Если я попытаюсь установить nodeDrawFunction, например, с помощью:

test2 :: (Show a) => Graph a -> Settings a
test2 g = def & nodeDrawFunction .~ drawDefaultNode
              & bgOp .~ Just 1

Выдается следующая ошибка:

Could not deduce (Show a10) arising from a use of ‘def’
  from the context: Show a
    bound by the type signature for:
               test2 :: forall a. Show a => Graph a -> Settings a
    at Visualise/Hierarchical.hs:78:1-42
  The type variable ‘a10’ is ambiguous
  These potential instances exist:
    instance Show n => Show (Duration n) -- Defined in ‘Data.Active’
    instance Show n => Show (Era n) -- Defined in ‘Data.Active’
    instance Show n => Show (Time n) -- Defined in ‘Data.Active’
    ...plus 74 others
    ...plus 264 instances involving out-of-scope types
    (use -fprint-potential-instances to see them all)
• In the first argument of ‘(&)’, namely ‘def’
  In the first argument of ‘(&)’, namely
    ‘def & nodeDrawFunction .~ drawDefaultNode’
  In the expression:
    def & nodeDrawFunction .~ drawDefaultNode & bgOp .~ Just 1

Даже если я попытаюсь установить nodeDrawFunction в значение по умолчанию (как и любую другую допустимую функцию).

Любая помощь будет высоко оценена, спасибо!


person Sam Prescott    schedule 07.11.2018    source источник


Ответы (1)


Вероятно, вы предполагаете, что def и def & nodeDrawFunction .~ drawDefaultNode имеют один и тот же тип. nodeDrawFunction достаточно гибок, чтобы иметь разные типы, Settings a и Settings a10. GHC начинает с этого более общего предположения, а затем не может выбрать конкретный тип для a10, так как он ничем не ограничен в функции.

Один из вариантов — определить nodeDrawFunction с менее общим типом.

Другой вариант — добавить сигнатуру типа на def для руководства GHC. Я думаю, это сработает, если вы добавите -XScopedTypeVariables:

(def :: Settings a) & nodeDrawFunction .~ drawDefaultNode

Без ScopedTypeVariables две переменные типа a интерпретируются как разные, и перед проверкой типов им присваиваются разные уникальные имена. Если бы у вас было несколько полей в Settings, которые включали бы a, makeLenses получили бы линзы, которые не могут изменить a, поскольку ни одна линза с одним полем не может этого сделать.

person bergey    schedule 07.11.2018
comment
Большое спасибо! Я пробовал это, но забыл включить расширение ScopedTypeVariables :) - person Sam Prescott; 07.11.2018
comment
ScopedTypeVariables находится в моем коротком списке, который я хотел бы видеть включенным по умолчанию в будущем GHC :) - person bergey; 07.11.2018