Моих типов данных всегда будут иметь по крайней мере два параметра, а последние два параметра всегда «д» и «т», соответственно:Тип Деконструкция
{-# LANGUAGE TypeFamilies, FlexibleContexts, UndecidableInstances, TypeOperators, DataKinds, ConstraintKinds, FlexibleInstances #-}
data D1 q m = D1 q
data D2 t q m = D2 q
class Foo a where -- a has kind * -> *
f :: a x -> a x
class (Foo b) => Bar b where -- b has kind * -> *
-- the purpose of g is to change ONE type parameter, while fixing the rest
-- the intent of the equality constraints is to decompose the parameter b into
-- its base type and 'q' parameter, then use the same base type with a *different*
-- `q` parameter for the answer
g :: (b ~ bBase q1, b' ~ bBase q2) => b m -> b' m
instance (Foo (D2 t q), Integral q) => Bar (D2 t q) where
g (D2 q) = D2 $ fromIntegral q -- LINE 1
результаты этой программы в ошибке
Could not deduce (bBase ~ D2 t0) (LINE 1)
Когда я написал экземпляр, я, конечно, намеревался указать bBase ~ D2 t
. Я думаю, что t не связано каким-то образом (следовательно, введение t0), и я не знаю, может ли GHC деконструировать этот тип вообще. Или, может быть, я просто делаю что-то глупое.
Более того, этот тип разложения типа/декомпозиции типа не требовался бы, если я делаю параметр для Bar имеющим вид * -> * -> *. Но тогда я не мог принудить Foo ограничение:
class (Foo (b q)) => Bar b where -- b has kind * -> * -> *
g :: b q m -> q b' -- this signature is now quite simple, and I would have no problem implementing it
Это не будет работать, потому что д не является параметром для бара, и я не хочу его параметра Bar.
Я нашел решение, используя два дополнительных «пустышку» связанные типы, но я действительно не нравится иметь их вокруг, если я не нуждаюсь в них:
class (Foo b, b ~ (BBase b) (BMod b)) => Bar b where -- b has kind * -> *
type BBase b :: * -> * -> *
type BMod b :: *
g :: (Qux (BMod b), Qux q') => b m -> (BBase b) q' m
instance (Foo (D2 t q), Integral q) => Bar (D2 t q) where
type BBase (D2 t q) = D2 t
type BMod (D2 t q) = q
g (D2 q) = D2 $ fromIntegral q
Это работает, но оно составляет явно деконструируя тип, который, я думаю, должен быть ненужным, учитывая простой тип экземпляра.
Я ищу решение для любого подхода: либо скажите мне, как я могу принудить ограничение класса к «более прикладному» типу, либо расскажу, как сделать типы GHC-деконструирования.
Спасибо!
сообщение полной ошибки я получаю 'amy16.hs: 7: 1: Нелегального Эквационального ограничения б ~ BBASE q1 (Используйте -XGADTs или -XTypeFamilies, чтобы разрешить это) При проверке метода класса: g :: forall (bBase :: * -> * -> *) q1 (b ':: * -> *) q2 m. (b ~ bBase q1, b '~ bBase q2) => bm -> b' m В объявлении класса для 'Bar ' Ошибка, модули загружены: нет.' Поэтому я думаю, вам нужно добавить либо ' GADTs, или прагма 'TypeFamilies', и, возможно, некоторые другие прагмы. – mhwombat
Я не использовал компиляцию флагов/языковых прагм в приведенном выше коде, но, конечно, я использую все, что мне нужно, в этих терминах (что должно заставить все фрагменты работать): TypeFamilies, FlexibleContexts, UndecidableInstances, TypeOperators, DataKinds , ConstraintKinds, FlexibleInstances – crockeea