2011-12-24 16 views
5

Jaki jest najlepszy sposób, abyRepa --- Jak utworzyć instancję odczytu?

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

instancję czytać? Więc później mógłbym wyprowadzić jako instancję Czytaj również.

+0

Podejrzewam, że nie można utworzyć "pełnej" instancji odczytu. Ogólnie rzecz biorąc, ważne typy danych będą już mieć instancje odczytu, jeśli autor uzna, że ​​mają sens. Typ 'Array' w Repa ma funkcje wyższego rzędu wewnątrz jego komponentów -' Generator' i 'Range', które nie mogą być tworzone jako instancje Read. Wyobrażam sobie, że właściwym rozwiązaniem jest przekształcenie/odserializowanie danych w prostszy format. –

Odpowiedz

6

Takim przykładem będzie orphan instance, którego należy zasadniczo unikać. Jednakże, jest to dość proste do napisania go:

{-# 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 

Jeśli używasz rozszerzenia StandaloneDeriving dwa pierwsze przypadki można uprościć:

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

te przypadki powinny prawdopodobnie w samej Repa; Właśnie oparłem je na przykładowej instancji podanej w Text.Show i wyjściu z repa na show. Proponuję wysłanie prośby o funkcję do repa za bug tracker i umieszczenie tych instancji w module twojego programu na teraz (chyba, że ​​chcesz całkowicie uniknąć osieroconych instancji, w takim przypadku będziesz musiał rozwiązać problem w zupełnie inny sposób).


Powiedział, że powinieneś rozważyć po prostu konwersji danych do listy (z toList) i za pomocą tego; omija instancję osieroconą i nie powinien mieć żadnych wad. Możesz także rozważyć użycie "prawdziwej" biblioteki do serializacji, takiej jak cereal, jeśli bardziej interesuje Cię przetwarzanie danych za pomocą kodu niż czytanie w zrozumiały dla człowieka sposób; Read jest generalnie uważany za raczej ograniczony użytek.

+0

Typ 'Array' w Repa jest tworzony z listy regionów, które zawierają' Range' i 'Generator', oba Range an Generator mają funkcje wyższego rzędu jako komponenty, więc nie mogą być rzeczywiście tworzone w instancjach Read. –

+0

@stephentetley: Cała instancja 'Read' musi być w stanie przetworzyć poprawny kod Haskella odpowiadający wyjściom instancji' Show'. – ehird

+0

'show $ R.fromFunction (Z:. (10 :: Int)) (const 42)' = '" Array (Z:. 10) [42,42, 42,42, 42,0, 42,42, 42,0, 42,0, 42,0, 42.0,42.0] "', które moja instancja poprawnie analizuje. – ehird

Powiązane problemy