Как я могу автоматически вывести Read
экземпляр для этого GADTs:Выводя прочитанной Инстансы для GADTs
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data TypeDec a where
TypeDecInt :: TypeDec Int
TypeDecString :: TypeDec String
deriving instance Show (TypeDec a)
data Bar where
Bar :: (Show a, Read a) => TypeDec a -> a -> Bar
deriving instance Show Bar
Идея заключается в том, что Bar
является сериализации типа.
Я могу написать Read
экземпляр, следующий фрагмент или Parsec, но учитывая, что у меня есть много подобных типов в TypeDec
и Bar
в различных модулях этого является шаблонный:
instance Read Bar where
readsPrec _ s =
let (bar, tup) = second breaks . breaks $ s
in if "Bar" == bar then uncurry parse tup else []
where
parse :: String -> String -> [(Bar, String)]
parse tdec = case tdec of
"TypeDecInt" -> parse' TypeDecInt
"TypeDecString" -> parse' TypeDecString
_ -> const []
parse' :: (Show a, Read a) => TypeDec a -> String -> [(Bar, String)]
parse' tdec s = [(Bar tdec (read s), "")]
breaks :: String -> (String, String)
breaks = second (drop 1) . break (== ' ')
Это полностью выполнимо с использованием шаблона Haskell. Нужно просто использовать подход, упомянутый @dfeuer (т. Е. Используя 'case' вместо' GHC.Read.choose'). – Alec
@Alec Вы знаете какой-либо пример/учебник для получения экземпляров 'Read' с шаблоном Haskell? – homam
[Это] (https://wiki.haskell.org/Template_haskell/Instance_deriving_example) выглядит хорошо. – Alec