Haskell: definiciones de instancias para familias de tipos
Digamos que tenemos el siguiente código:
class C t where
g :: t
instance C Int where
g = 42
Sencillo. También podemos definir funciones en Int, así:
f1 :: Int -> Int
f1 x = x * x
He estado trabajando con familias tipográficas, en particular porqueData.Has
los utiliza, y quiero insertarlos en unIxSet
.
Pero aquí voy a presentar un ejemplo simplificado. Digamos que queremos definir un nuevo tipoX
, que es similar a un int. Podríamos hacer esto:
type family X
type instance X = Int
Entonces podemos definir funciones enX
al igual que:
f2 :: X -> X
f2 x = x * x + 1
No hay problemas hasta ahora. Ahora vamos a tratar de definir una instanciaC X
, como hicimos paraC Int
:
instance C X where
g = 43
Uh oh, ahora tenemos el siguiente error:
Aplicación de familia de sinónimos de tipo ilegal en la instancia:X
En la declaración de instancia para'C X'
Ahora intentemos algo un poco diferente:
newtype NewX = NewX X
instance C NewX where
g = 43
Ahora tenemos otro error, a saber:
Ninguna instancia para(Num NewX)
surgiendo de lo literal'43'
Parece que elnewtype
la palabra clave elimina cualquier información sobre a qué clases pertenecía la clase anterior. Sin embargo, también parece que no puedo evitarnewtype
, ya que no puedo usar familias de tipos en definiciones de instancia.
¿Hay una mejor manera de hacerlo sin tener que volver a escribir definiciones de instancia con menciones explícitas adicionales de instancias que de lo contrario se deducirían?
Información de fondo:
La razón por la que necesito que esto funcione es la siguiente:
import Data.Has
import Data.IxSet
data Col1 = Col1; type instance TypeOf Col1 = Text
data Col2 = Col2; type instance TypeOf Col2 = Text
type Row = FieldOf Col1 :&: FieldOf Col2;
instance Indexable Row where
empty = ixSet [ixFun $ (\x -> [ Col1 ^. x ]) ] -- Maybe add some more indexes later
Esto falla con:
Aplicación de familia de sinónimos de tipo ilegal en la instancia:Row
En la declaración de instancia para'Indexable Row'
FabricaciónRow
a newtype
provoca el siguiente error:
Ninguna instancia para (Contiene (Etiquetado Col1 Texto) Fila) que surja de un uso de '^.' Posible solución: agregue una declaración de instancia para la fila (Contiene (Texto Col1 Etiquetado))
La única manera de solucionar esto es agregando una cláusula de derivación larga de la siguiente manera:
newtype Row = Row (FieldOf Col1 :&: FieldOf Col2)
deriving
(
Contains (Labelled Col1 Text), -- Add this for every column
Contains (Labelled Col2 Text) -- ...
)
Incluso algo que me permite "typedef"Contains (Labelled x (TypeOf x))
decirHasCol x
sería de ayuda.