Что означает эта переменная типа «Неоднозначный» в ограничении? - PullRequest
5 голосов
/ 12 января 2012

В этом коде я пытаюсь, чтобы первый параметр в моей рабочей функции go был типом 'семейства типов'.Я вижу, что в документации семейств типов аналогичная функция insert принадлежит классу типов, в то время как в моем примере ниже это не так.

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

{-# LANGUAGE TypeFamilies #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

--| A map
data (K a) => M a b = M a b

insert :: (K a) => a -> b -> M a b -> M a b
insert = go mkI    -- <<< PROBLEM
  where
    go o a b m = m

Неоднозначная переменная типа `a 'в ограничении:

`K a'

  arising from an expression type signature at Data/Map2.hs:167:10-33

Вероятное исправление: добавить типподпись, которая исправляет эти переменные типа

1 Ответ

10 голосов
/ 12 января 2012

Это компилируется:

{-# LANGUAGE TypeFamilies, GADTs, ScopedTypeVariables #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

-- | A map
data M x y where
    M :: K a => a -> b -> M a b

insert :: forall a b. (K a) => a -> b -> M a b -> M a b
insert = go mkI
  where
    go :: (a -> I a) -> a -> b -> M a b -> M a b
    go o a b m = m

Что я изменил и почему?

Во-первых, я предположил, что вы хотели установить ограничение на M, поэтому я использовал форму определения типа, которая применяет ограничение и делает его доступным на сайтах использования, GADT.

Во-вторых, проблема, на которую жаловался ваш GHC, двусмысленность. Дело в том, что компилятор не может определить , который mkI он должен использовать, поэтому мы должны сказать это. Для этого мы должны поместить переменные типа, используемые в области видимости, а затем указать компилятору в локальной подписи, какой экземпляр типа использовать.

...