Как лучше всего сделать
type Configuration = Array DIM1 (Double, Double, Double)
экземпляр чтения? Так что позже я мог вывести
data SimulationData = SD Configuration Double StdGen Int
быть экземпляром Read тоже.
Как лучше всего сделать
type Configuration = Array DIM1 (Double, Double, Double)
экземпляр чтения? Так что позже я мог вывести
data SimulationData = SD Configuration Double StdGen Int
быть экземпляром Read тоже.
Такой экземпляр будет сиротским экземпляром, чего обычно следует избегать. Однако написать его довольно просто:
{-# 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
Если вы используете расширение StandaloneDeriving
, первые два экземпляра можно упростить:
deriving instance Read Z
deriving instance (Read tail, Read head) => Read (tail :. head)
Эти экземпляры, вероятно, должны быть в самой repa; Я просто основывал их на экземпляре примера, приведенном в Text.Show и вывод repa show
. Я предлагаю сделать запрос функции на системе отслеживания ошибок repa и поместить эти экземпляры в модуль вашей программы на данный момент (если вы не хотите избежать экземпляры-сироты полностью, и в этом случае вам придется решать проблему совсем другим способом).
Тем не менее, вам, вероятно, следует подумать о простом преобразовании ваших данных в список (с toList
) и его использовании; он избегает экземпляра-сироты и не должен иметь никаких недостатков. Вы также можете рассмотреть возможность использования «настоящей» библиотеки сериализации, такой как cereal, если вас больше интересует обработка данных с помощью код, чем то, что он должен быть удобочитаемым; Read
обычно считается довольно ограниченным применением.
Array
в Repa состоит из списка регионов, которые содержат Range
и Generator
, оба Range и Generator имеют функции более высокого порядка в качестве компонентов, поэтому их нельзя сделать экземплярами Read.
- person stephen tetley; 24.12.2011
Read
, — это анализировать допустимый код Haskell, который выводит соответствующий экземпляр Show
.
- person ehird; 24.12.2011
show $ R.fromFunction (Z :. (10::Int)) (const 42)
= "Array (Z :. 10) [42.0,42.0,42.0,42.0,42.0,42.0,42.0,42.0,42.0,42.0]"
, что правильно анализирует мой экземпляр.
- person ehird; 24.12.2011
Show
нарушает здесь правила, поскольку этот код не печатает, но это правило часто нарушается (например, Data.ByteString.Char8
экспортирует экземпляр Show
для ByteStrings, который работает, только если вы включите OverloadedStrings
, и я думаю, что экземпляр Show
для lazy ByteStrings фактически использует неэкспортированные конструкторы).
- person ehird; 24.12.2011
Show
и Read
были семантически действительными, Haskell не имеет практического смысла. Однако синтаксис имеет значение, так как в противном случае было бы трудно определить корректно работающие экземпляры для типов контейнеров, таких как [a]
, которые должны взаимодействовать с экземплярами для типа элемента.
- person hammar; 24.12.2011
Show
в основном полезен только для отладки (для чего он, конечно, очень полезен), а Read
полезен только для игрушечных программ, поэтому я могу ценить семантически правильные экземпляры больше, чем другие.
- person ehird; 24.12.2011
Just arr
, это дает мне *** Исключение: Prelude.read: нет разбора, хотя разбор самих массивов или кортежей работает.
- person Yrogirg; 25.12.2011
Show
repa: он показывает Just arr
как Just Array (Z :. 10) [...]
без необходимых скобок. Изменение readsPrec d = readParen (d > app) $ \r -> do
на readsPrec d r = do
должно заставить мой экземпляр работать в этом случае, но, к сожалению, то, что делает repa, вызывает внутреннюю двусмысленность; вы должны сообщить об этом как об ошибке.
- person ehird; 25.12.2011
Array
в Repa имеет функции более высокого порядка внутри своих компонентов —Generator
иRange
, которые нельзя сделать экземплярами Read. Я полагаю, что правильно будет сериализовать/десериализовать ваши данные в более простой формат. - person stephen tetley   schedule 24.12.2011