Создание экземпляра класса 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).

Если стандартного деривации недостаточно, для такого типа, как ваш, это просто набор Ints вы можете игнорировать параметр приоритета.

КСТАТИ, Read а также Show довольно медленные; Вы можете рассмотреть другие способы ввода / вывода с вашими данными.

Это потому, что метод класса, который вы, вероятно, захотите реализовать, это readsPrec. Смотрите здесь для получения полной информации о типе чтения Read: http://zvon.org/other/haskell/Outputprelude/Read_c.html

Кстати, вы должны иметь возможность просто использовать автоматическую деривацию, и компилятор создаст для вас эти методы Read, например:

data Foo = Foo Int Int
           deriving (Read, Show)
Другие вопросы по тегам