2011-12-24 9 views
5

¿Cuál es la mejor manera de hacerRepa --- ¿Cómo hacer una instancia de lectura?

type Configuration = Array DIM1 (Double, Double, Double) 

una instancia de Lee? Así que más tarde podría derivar

data SimulationData = SD Configuration Double StdGen Int 

para ser una instancia de Leer también.

+0

Sospecho que no puede hacer una instancia de lectura "completa". En general, los tipos de datos importantes ya tendrán instancias de lectura si el autor cree que tienen sentido. El tipo 'Array' en Repa tiene funciones de orden superior dentro de sus componentes -' Generator' y 'Range' que no pueden ser instancias de Read. Me imagino que lo correcto es serializar/deserializar sus datos en un formato más simple. –

Respuesta

6

Tal instancia será una orphan instance, que generalmente debe evitar. Sin embargo, es bastante fácil de escribir que:

{-# LANGUAGE TypeOperators #-} 

import Data.Array.Repa (Array, Shape, Elt, Z(..), (:.)(..)) 
import qualified Data.Array.Repa as R 

instance Read Z where 
    readsPrec _ r = do 
    ("Z", s) <- lex r 
    return (Z, s) 

instance (Read tail, Read head) => Read (tail :. head) where 
    readsPrec d = 
    readParen (d > prec) $ \r -> do 
     (tl, s) <- readsPrec (prec + 1) r 
     (":.", t) <- lex s 
     (hd, u) <- readsPrec (prec + 1) t 
     return (tl :. hd, u) 
    where prec = 3 

instance (Shape sh, Read sh, Elt a, Read a) => Read (Array sh a) where 
    readsPrec d = 
    readParen (d > app) $ \r -> do 
     ("Array", s) <- lex r 
     (sh, t) <- readsPrec (app + 1) s 
     (xs, u) <- readsPrec (app + 1) t 
     return (R.fromList sh xs, u) 
    where app = 10 

Si utiliza la extensión StandaloneDeriving, los dos primeros casos se pueden simplificar:

deriving instance Read Z 
deriving instance (Read tail, Read head) => Read (tail :. head) 

Estos casos probablemente debería ser en sí mismo repa; Simplemente los basé en la instancia de ejemplo dada en Text.Show y en la salida show de repa. Sugiero hacer una solicitud de función en el bug tracker de repa y poner estas instancias en un módulo de tu programa por ahora (a menos que quieras evitar completamente las instancias huérfanas, en cuyo caso tendrás que resolver el problema de otra manera).


Dicho esto, usted debe considerar probablemente simplemente convertir sus datos en una lista (con toList) y el uso de eso; evita la instancia huérfana y no debería tener inconvenientes. También puede considerar el uso de una biblioteca de serialización "real" como cereal si está más interesado en procesar los datos con código que en que sean legibles por el ser humano; Read generalmente se considera de uso bastante limitado.

+0

El tipo 'Array' en Repa se crea a partir de una lista de Regiones que contienen' Range' y 'Generator', ambos Range an Generator tienen funciones de orden superior como componentes, por lo que no pueden convertirse en instancias de Read. –

+0

@stephentetley: Todo lo que una instancia 'Read' tiene que poder hacer es analizar el código Haskell válido que emite la instancia' Show 'correspondiente. – ehird

+0

'show $ R.fromFunction (Z:. (10 :: Int)) (const 42)' = '" Matriz (Z: .10) [42.0,42.0,42.0,42.0,42.0,42.0,42.0,42.0, 42.0,42.0] "', que mi instancia analiza correctamente. – ehird

Cuestiones relacionadas