Проблема при смешивании классов типа и семейств шрифтов

Этот код прекрасные компиляции:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
  UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
  TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
  type Res a s b :: *

instance Sel a s b where
  type Res a s b = (s -> (b,s))

instance Sel a s (b->(c,a)) where
  type Res a s (b->(c,a)) = (b -> s -> (c,s))

но как только я добавляю предикат R ghc сбои:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
  UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
  TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
  type Res a s b :: *

instance Sel a s b where
  type Res a s b = (s -> (b,s))

class R a where
  type Rec a :: *
  cons :: a -> Rec a
  elim :: Rec a -> a
instance Sel a s (b->(c,Rec a)) where
  type Res a s (b->(c,Rec a)) = (b -> s -> (c,s))

жалуясь, что:

    Illegal type synonym family application in instance:
        b -> (c, Rec a)
    In the instance declaration for `Sel a s (b -> (c, Rec a))'

что означает и (самое главное) как я фиксирую его?

Спасибо

9
задан Don Stewart 18 April 2011 в 23:30
поделиться

3 ответа

Семейства типов односторонние: вы можете расширить Rec a до его вычисляемого типа, но вы не можете (однозначно) перейти от расширение обратно к Rec a . Это делает приложения функций типа непригодными для экземпляров сигнатур, поскольку они никогда не могут инициировать применение экземпляра.

Вместо этого вы можете попробовать:

instance Rec a ~ reca => Sel a s (b->(c,reca))

Это означает другое: в нем говорится, что любая функция b -> (c, reca) является экземпляром, а затем, когда она безвозвратно сопоставлена, компилятор проверяет, что Запись . Но в вашем случае этого может быть достаточно.

12
ответ дан 4 December 2019 в 14:27
поделиться

Rec не является конструктором типа; это функция типа. Может быть, вы можете использовать его только в типе значения определения типа, а не в объявлении класса? Я здесь дико догадываюсь; Я не понимаю всех правил типовых семей.

Я не знаю, как это исправить, но кое-что, что можно попробовать, включает:

  • Избавьтесь от класса Sel и просто определите семейство типов Res a s b :: * . Используйте экземпляр типа вместо механизма классов.

  • Едва ли возможно, что создание инъективного типа Rec с использованием данных поможет, но я так не думаю.

  • Сократите до минимального количества языковых расширений, которые могли бы работать - это упростит другим помощь вам, а также может помочь компилятору.

1
ответ дан 4 December 2019 в 14:27
поделиться

Это означает, что вам не разрешено использовать семейства синонимов типов при объявлении экземпляров типов. См. Раздел «Семейства типов и объявления экземпляров» руководства GHC.

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

1
ответ дан 4 December 2019 в 14:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: