Haskell: взаимодействие между ConstraintKinds и TypeSynonymInstances - PullRequest
0 голосов
/ 28 октября 2018

Я получаю неожиданную ошибку при попытке скомпилировать небольшой файл Haskell с GHC 8.6.1 при использовании ConstraintKinds и TypeSynonymInstances.

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

{-# LANGUAGE ConstraintKinds, KindSignatures, TypeSynonymInstances #-}

module TypeAlias where

import Data.Kind

class Foo a
class Bar a

class Baz (c :: * -> Constraint)

instance Baz Foo -- compiles
instance Baz Bar -- compiles

type FooBar a = (Foo a, Bar a) -- compiles

instance Baz FooBar -- fails!
-- TypeAlias.hs:17:10-19: error:
--     • The type synonym ‘FooBar’ should have 1 argument, but has been given none
--     • In the instance declaration for ‘Baz FooBar’
--    |
-- 17 | instance Baz FooBar
--    |          ^^^^^^^^^^

Ошибка удивительна, потому что, насколько я могу судить, FooBar имеет ожидаемый вид, а именно * -> Constraint, но компилятор говорит, что ему следует передать аргумент.

Можно ли вообще использовать псевдоним ограничения в объявлении экземпляра, как я здесь пытаюсь?Если да, то как мне понять кажущееся противоречивым сообщение об ошибке?

(я знаю, что могу просто объявить FooBar как класс вместо псевдонима, но я действительно не хочу, потому что я 'Я также хотел бы получить экземпляр, и в этот момент мне пришлось бы задействовать UndecidableInstances.)

1 Ответ

0 голосов
/ 29 октября 2018

Оказывается, Эд Кметт ответил на мой вопрос год назад.Я не могу сделать это с псевдонимами типов, но использование UndecidableInstances должно быть благоприятным для этой конкретной ситуации:

https://www.reddit.com/r/haskell/comments/5zjwym/when_is_undecidableinstances_okay_to_use/

Вот как Kmett может предложить исправить приведенный выше пример:

{-# LANGUAGE ConstraintKinds, FlexibleInstances,
             KindSignatures, UndecidableInstances #-}

module NotTypeAlias where

import Data.Kind

class Foo a
class Bar a

class Baz (c :: * -> Constraint)

instance Baz Foo -- compiles
instance Baz Bar -- compiles

class (Foo a, Bar a) => FooBar a
instance (Foo a, Bar a) => FooBar a -- compiles

instance Baz FooBar -- compiles

Кметт утверждает, что если экземпляр FooBar, который мы предоставляем, является единственным экземпляром, когда-либо находящимся в области действия, то средство проверки типов не попадет в бесконечный цикл из-за использования нами UndecidableInstances.Я доволен, что поверил ему на слово.

...