Когда (если вообще) можно ли частично применять синонимы типа?
Видимо, немного рассеянно, я написал что-то вроде следующего:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
class Foo f where
type Bar f :: *
retbar :: Bar f -> IO f
type Baz f = (Foo f, Eq f)
-- WithBar :: * -> (*->Constraint) -> * -> Constraint
type WithBar b c f = (c f, Bar f ~ b)
instance Foo () where
type Bar () = ()
retbar = return
naim :: WithBar () Baz u => IO u -- why can I do this?
naim = retbar ()
main = naim :: IO ()
Только после успешной компиляции я понял, что на самом деле это не должно работать: Baz
определяется как синоним типа с одним аргументом, но здесь я использую его без прямого аргумента. Обычно GHC лает на меня Type synonym ‘Baz’ should have 1 argument, but has been given none
когда я пытаюсь что-то подобное.
Не поймите меня неправильно: мне бы очень хотелось написать это, и достаточно просто увидеть, как это может работать в этом конкретном примере (просто WithBar
даст подпись naim :: (Foo u, Bar u ~ ()) => IO u
, что, конечно, хорошо), но что я не понимаю, почему это на самом деле так работает здесь. Это возможно только ошибка в ghc-7.8.2
разрешить это?
3 ответа
Ваш файл компилируется в GHC 7.8, но в GHC 7.10 я получаю ошибку:
Синоним типа 'Baz' должен иметь 1 аргумент, но ему не дано ни одного
В сигнатуре типа для 'naim': naim:: WithBar () Baz u => IO u
Добавление -XLiberalTypeSynonyms
исправляет ошибку. Поэтому это ошибка в 7.8.
Частичное приложение должно быть включено LiberalTypeSynonyms
расширение.
По сути, это откладывает большую часть проверки согласованности синонимов типов до тех пор, пока они не будут расширены, поэтому ваше "встроенное" объяснение по сути является правильной идеей.
Странная вещь здесь, однако, в том, что это расширение не подразумевается теми, что в вашем модуле. Я только что проверил, и частичное приложение не работает вообще с просто ConstraintKinds
, TypeFamilies
а также PolyKinds
, (Я добавил последний, потому что виды проверяются перед расширением, и в противном случае мои типы тестов были выведены неверно.)
Тем не менее, ваш файл прекрасно загружается для меня в GHCi 7.8.3. Может быть, это какая-то ошибка, даже если есть расширение, чтобы сделать его правильно легальным.
Я не знаю, каковы официальные правила, но для такого рода вещей кажется разумным работать на основе стратегии расширения синонимов крайнего левого типа. Единственное, что имеет значение, это то, что синонимы типа могут быть удалены в отдельной и завершающей фазе, прежде чем произойдет остальная проверка типов. Я не знаю, предполагается ли, что вы можете использовать частично примененный синоним типа F в качестве аргумента синонима другого типа G, если только G гарантирует, что F получает пропущенные аргументы, но это, безусловно, согласуется с идеей, что синонимы типа мелкое удобство.