[Haskell] Instance (Read MyType)
От: Andir Россия
Дата: 13.06.08 01:46
Оценка:
Привет, RSDN!

Пытаюсь разобраться, как перегрузить поведение Read для произвольного типа. Для Show всё просто, берёшь внутренности типа и складываешь их в строчку так как захотелось. Но вот как теперь из этой строчки считать значение: почему-то минимальное определение Read принимает не строчку, а чёрти что с лексемами.

data MyType = MyTypeT { a :: Int, b :: String }
    
instance (Show MyType) where
    -- show :: String -> MyType
    show (MyTypeT a b) = "MyTypeT " ++ "{ a = " ++ (show a) ++ ", b = " ++ b ++ " }"

instance (Read MyType) where
    -- readPrec :: ReadPrec MyType
    readPrec = {- ??? -}


Как же написать этот Read?
И зачем он сделан таким странным, а не просто функцией read которая принимала бы строку и возвращала бы Maybe instance?

P.S. readsPrec написать довольно просто, хотя и там странное возвращаемое значение и зачем-то введён аргумент приоритета.

С Уважением, Andir!
using( RSDN@Home 1.2.0 alpha 4 rev. 987 ) { /* Работаем */ }
Re: [Haskell] Instance (Read MyType)
От: deniok Россия  
Дата: 13.06.08 07:16
Оценка: 4 (1)
Здравствуйте, Andir, Вы писали:

A>Привет, RSDN!


A>Пытаюсь разобраться, как перегрузить поведение Read для произвольного типа. Для Show всё просто, берёшь внутренности типа и складываешь их в строчку так как захотелось. Но вот как теперь из этой строчки считать значение: почему-то минимальное определение Read принимает не строчку, а чёрти что с лексемами.


readsPrec позволяет делать синтаксический разбор.

A>Как же написать этот Read?

A>И зачем он сделан таким странным, а не просто функцией read которая принимала бы строку и возвращала бы Maybe instance?

Maybe недостаточно, может быть неоднозначный разбор, когда подходят несколько вариантов.

A>P.S. readsPrec написать довольно просто, хотя и там странное возвращаемое значение и зачем-то введён аргумент приоритета.


Вроде здесь
Автор(ы): Пол Хьюдак, Джон Петерсон, Джозеф Фасел
Дата: 24.04.2007
Данный материал – продолжение начатого в прошлом номере введения в программирование на Haskell для имеющих опыт программирования, по крайней мере, на одном языке, желательно функциональном (даже если это «почти функциональный» язык, такой как ML или Scheme).
все более-менее понятно описано на примере разбора дерева.
Re[2]: [Haskell] Instance (Read MyType)
От: Andir Россия
Дата: 13.06.08 09:19
Оценка:
Здравствуйте, deniok, Вы писали:

A>>P.S. readsPrec написать довольно просто, хотя и там странное возвращаемое значение и зачем-то введён аргумент приоритета.

D>Вроде здесь
Автор(ы): Пол Хьюдак, Джон Петерсон, Джозеф Фасел
Дата: 24.04.2007
Данный материал – продолжение начатого в прошлом номере введения в программирование на Haskell для имеющих опыт программирования, по крайней мере, на одном языке, желательно функциональном (даже если это «почти функциональный» язык, такой как ML или Scheme).
все более-менее понятно описано на примере разбора дерева.


Ага, прочитал. Там что-то торкнуло, и я смог разобрать:
-- Стандартный вариант лексического разбора (Haskell 98)
instance (Read MyType) where
    readsPrec _ s = [ (MyTypeT a b, s') ]
        where 
            [("MyTypeT", s1)] = lex s
            [("{", s2)] = lex s1
            [("a", s3)] = lex s2
            [("=", s4)] = lex s3
            [(a, s5)] = reads s4
            [(",", s6)] = lex s5
            [("b", s7)] = lex s6
            [("=", s8)] = lex s7
            [(b, s9)] = lex s8
            [("}", s')] = lex s9

-- Вариант лексического разбора для GHC-расширений
instance (Read MyType) where
    readPrec = do
        Ident "MyTypeT" <- lexP
        Punc "{" <- lexP
        Ident "a" <- lexP
        Punc "=" <- lexP
        Int a <- lexP
        Punc "," <- lexP
        Ident "b" <- lexP
        Punc "=" <- lexP
        Ident b <- lexP
        Punc "}" <- lexP
        return $ MyTypeT (fromInteger a) b
    
-- Прямолинейный вариант разбора с помощью регулярных выражений
instance (Read MyType) where
    readsPrec _ s 
        | matchResult == Nothing = []
        | otherwise = [ (MyTypeT (read stra) strb, "") ] 
        where 
            r = mkRegex "MyTypeT { a = ([1-9][0-9]*), b = (.+) }"
            matchResult = matchRegex r s
            Just [stra, strb] = matchResult


Я ничего не упустил, так оно и должно выглядеть в общем виде?

С Уважением, Andir!
using( RSDN@Home 1.2.0 alpha 4 rev. 987 ) { /* Работаем */ }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.