2011-04-02 9 views
20

Tengo un tipo de datos personalizado Foo = Foo{ a :: Int, b :: Int} y estoy tratando de hacer de Foo una instancia personalizada de lectura. Ya tengo una función y he intentado hacer esto:Creando una instancia de la clase de tipo de lectura en Haskell para el tipo de datos personalizado

instance Read (Foo a b) where 
    read s = bar s 

pero yo estoy recibiendo el siguiente error cuando cargo mi archivo en GHCi para probarlo: Fraction.hs:11:1: read' is not a (visible) method of class Read'

Podría alguien decirme cuál es el problema es y cómo puedo crear una instancia de este tipo?

Respuesta

18

La clase de tipos Read no lo hace declarar read directamente; en su lugar, define readsPrec, que admite precedencia (esto es importante cuando read es un valor de un tipo de datos complejo que involucra elementos de otros tipos). La definición se obtiene cuando se utiliza deriving (Read) se ve más o menos así

instance (Read a) => Read (Tree a) where 

    readsPrec d r = readParen (d > app_prec) 
        (\r -> [(Leaf m,t) | 
          ("Leaf",s) <- lex r, 
          (m,t) <- readsPrec (app_prec+1) s]) r 
        ++ readParen (d > up_prec) 
        (\r -> [(u:^:v,w) | 
          (u,s) <- readsPrec (up_prec+1) r, 
          (":^:",t) <- lex s, 
          (v,w) <- readsPrec (up_prec+1) t]) r 
     where app_prec = 10 
      up_prec = 5 

(esto, obviamente, para un tipo de datos Tree, pero se aplican reglas similares para otros TDAs definidos por el usuario). (Además, lo anterior es una pequeña mentira: GHC realmente utiliza una implementación diferente, pero lo anterior es el tipo de cosas que debe hacer a menos que esté dispuesto a excavar dentro de GHC.)

read se define en términos de readsPrec y (el otro método en Read, que está predeterminado para todos los tipos excepto Char donde se usa para leer [Char] como una cadena en lugar de como una lista de Char).

Si la derivación estándar no es suficiente, para un tipo como el suyo que es simplemente un depósito de Int s puede ignorar el parámetro de precedencia.

BTW, Read y Show son bastante lentos; Es posible que desee considerar otras formas de hacer E/S con sus datos.

+11

¿Tiene alguna sugerencia de alternativas para leer y mostrar? – user381261

3

Esto se debe a que el método de clase que probablemente desee implementar es lee Prec. Ver aquí para obtener información completa sobre Lee clase de tipos: http://zvon.org/other/haskell/Outputprelude/Read_c.html

Por cierto, usted debería ser capaz de usar sólo la derivación automática y el compilador creará una instancia de esos métodos de lectura para usted, por ejemplo:

data Foo = Foo Int Int 
      deriving (Read, Show) 
+1

Sé que puedo hacer eso, pero realmente no me gusta la forma en que la lectura se realiza automáticamente, ya que es menos intuitiva y quería hacer una versión mejor. – user381261

Cuestiones relacionadas