Здравствуйте, 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).
все более-менее понятно описано на примере разбора дерева.
Привет, 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 ) { /* Работаем */ }
Здравствуйте, 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 ) { /* Работаем */ }