Создание экземпляра класса Read type в Haskell для пользовательского типа данных
У меня есть пользовательский тип данных Foo = Foo{ a :: Int, b :: Int}
и я пытаюсь сделать Foo пользовательским экземпляром для чтения. У меня уже есть функция bar :: String -> Foo
и я попытался сделать это:
instance Read (Foo a b) where
read s = bar s
но я получаю следующую ошибку при загрузке файла в GHCi для его проверки: Fraction.hs:11:1: read' is not a (visible) method of class Read'
Может кто-нибудь сказать мне, в чем проблема и как я могу на самом деле создать этот тип?
2 ответа
Класс типов чтения не объявляет read
непосредственно; вместо этого он определяет readsPrec
, который поддерживает приоритет (это важно, когда read
значение сложного типа данных, включающее элементы других типов). Определение, которое вы получаете, когда используете deriving (Read)
выглядит примерно как
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
(это очевидно для Tree
тип данных, но аналогичные правила применяются для других пользовательских ADT). (Кроме того, вышесказанное является небольшой ложью: GHC на самом деле использует другую реализацию, но вышеописанное - это то, что вы должны делать, если только вы не хотите копаться в GHC.)
read
определяется с точки зрения readsPrec
а также readList
(другой метод в Read
, который по умолчанию для каждого типа, кроме Char
где он используется для чтения [Char]
в виде строки, а не в виде списка Char
).
Если стандартного деривации недостаточно, для такого типа, как ваш, это просто набор Int
s вы можете игнорировать параметр приоритета.
КСТАТИ, Read
а также Show
довольно медленные; Вы можете рассмотреть другие способы ввода / вывода с вашими данными.
Это потому, что метод класса, который вы, вероятно, захотите реализовать, это readsPrec. Смотрите здесь для получения полной информации о типе чтения Read: http://zvon.org/other/haskell/Outputprelude/Read_c.html
Кстати, вы должны иметь возможность просто использовать автоматическую деривацию, и компилятор создаст для вас эти методы Read, например:
data Foo = Foo Int Int
deriving (Read, Show)