Haskell: definiciones de instancias para familias de tipos
Digamos que tenemos el siguiente código:
<code>class C t where g :: t instance C Int where g = 42 </code>
Sencillo. También podemos definir funciones en Int, así:
<code>f1 :: Int -> Int f1 x = x * x </code>
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:
<code>type family X type instance X = Int </code>
Entonces podemos definir funciones enX
al igual que:
<code>f2 :: X -> X f2 x = x * x + 1 </code>
No hay problemas hasta ahora. Ahora vamos a tratar de definir una instanciaC X
, como hicimos paraC Int
:
<code>instance C X where g = 43 </code>
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:
<code>newtype NewX = NewX X instance C NewX where g = 43 </code>
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:
<code>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 </code>
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:
<code>newtype Row = Row (FieldOf Col1 :&: FieldOf Col2) deriving ( Contains (Labelled Col1 Text), -- Add this for every column Contains (Labelled Col2 Text) -- ... ) </code>
Incluso algo que me permite "typedef"Contains (Labelled x (TypeOf x))
decirHasCol x
sería de ayuda.