Этот код прекрасные компиляции:
{-# 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))'
что означает и (самое главное) как я фиксирую его?
Спасибо
Семейства типов односторонние: вы можете расширить Rec a
до его вычисляемого типа, но вы не можете (однозначно) перейти от расширение обратно к Rec a
. Это делает приложения функций типа непригодными для экземпляров сигнатур, поскольку они никогда не могут инициировать применение экземпляра.
Вместо этого вы можете попробовать:
instance Rec a ~ reca => Sel a s (b->(c,reca))
Это означает другое: в нем говорится, что любая функция b -> (c, reca)
является экземпляром, а затем, когда она безвозвратно сопоставлена, компилятор проверяет, что Запись
. Но в вашем случае этого может быть достаточно.
Rec
не является конструктором типа; это функция типа. Может быть, вы можете использовать его только в типе значения определения типа, а не в объявлении класса? Я здесь дико догадываюсь; Я не понимаю всех правил типовых семей.
Я не знаю, как это исправить, но кое-что, что можно попробовать, включает:
Избавьтесь от класса Sel и просто определите семейство типов Res a s b :: *
. Используйте экземпляр типа
вместо механизма классов.
Едва ли возможно, что создание инъективного типа Rec
с использованием данных
поможет, но я так не думаю.
Сократите до минимального количества языковых расширений, которые могли бы работать - это упростит другим помощь вам, а также может помочь компилятору.
Это означает, что вам не разрешено использовать семейства синонимов типов при объявлении экземпляров типов. См. Раздел «Семейства типов и объявления экземпляров» руководства GHC.
Единственный способ исправить это - провести рефакторинг, чтобы он каким-то образом не нуждался.