Problema quando si mescolano le classi di tipo e le famiglie di tipo
-
25-09-2019 - |
Domanda
Questo codice compila bene:
{-# 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))
, ma non appena aggiungo GHC R predicato fallisce:
{-# 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))
lamentando che:
Illegal type synonym family application in instance:
b -> (c, Rec a)
In the instance declaration for `Sel a s (b -> (c, Rec a))'
che cosa significa e (soprattutto) come posso risolvere il problema?
Grazie
Soluzione
famiglie tipo sono a senso unico: è possibile espandere Rec a
al suo tipo calcolata, ma non si può (unicamente) passare dal retro espansione Rec a
. Questo rende le applicazioni di funzioni di tipo inadatto per esempio le firme, in quanto non potranno mai far scattare l'istanza per applicare.
Si potrebbe provare invece:
instance Rec a ~ reca => Sel a s (b->(c,reca))
Questo significa un'altra cosa: si dice qualsiasi funzione b -> (c, reca)
è un esempio, e poi quando si è irrevocabilmente abbinate, i controlli del compilatore che Rec a ~ reca
. Ma questo potrebbe essere abbastanza buono per fare mancanza nel tuo caso.
Altri suggerimenti
Rec
non è un costruttore tipo; si tratta di una funzione di tipo. Forse si può utilizzare solo per il tipo di un valore di definizione di tipo, non in una dichiarazione di classe? Sto indovinando selvaggiamente qui; Non capisco tutte le regole per le famiglie tipo.
Non so come risolvere il problema, ma alcune cose da provare sono:
-
Sbarazzarsi di classe Sel e basta definire
type family Res a s b :: *
. Usotype instance
al posto del meccanismo della classe. -
E 'a malapena possibile che per fare il tipo
Rec
iniettiva utilizzandodata
aiuterà, ma io non la penso così. -
Taglia di nuovo al più piccolo numero di estensioni del linguaggio che potrebbe lavoro che renderà più facile per gli altri per aiutarti, e potrebbe aiutare il compilatore pure.
Ciò significa che non ti è permesso di utilizzare tipo famiglie synomym quando si dichiara istanze di tipo. Vedere la sezione "le famiglie di tipo e le dichiarazioni di istanza" del manuale GHC.
L'unico modo per risolvere il problema è quello di refactoring in modo da non averne bisogno in qualche modo.