# Polymorphism + Quasiquoting + Untyped AST = problems

3 messages
Open this post in threaded view
|

## Polymorphism + Quasiquoting + Untyped AST = problems

 Hi, Let me show you why I reached that conclusion through a simple example. Imagine that, for some reason, we need to implement a DSL which is required to use vectors. Furthermore, we would like to make transformations/sanity checks at compile time. To keep things simple, the vector is internally represented as a list: newtype Vec a = MkVec [a] -- Note that MkVec would be hidden to the end user. Using Template Haskell, we can easily create a constructor function which fulfils all the requirements. vector :: Lift a => [a] -> QExp vector xs = do sanityCheck xs                         [| MkVec xs |]  where sanityCheck = undefined -- not specified Using "vector" is simple: \$(vector [1,2,3,4,5]) OK, fair enough. However, pattern matching is lost and it would be nicer to be able to to build vector literals using a syntax different to lists. For example, using less-than and more-than symbols to enclose the vector elements: <1,2,3,4,5> We would also like to do some pattern matching: <>          -- empty vector x   -- head and tail of the vector Using a quasiquoter all the above is is possible. In the case of Int vectors, supposing name our quasiquoter v we could do things like. [\$v|<1,2,3,4,5,6>|] head  :: Vector Int -> Int f v = case v of           [\$v|<>|] -> error "empty"           [\$v|x|] -> x Looks nice, but we lose polymorphism! It is imposible  to make v work with any instance of Read! Here is a possible implementation: -- parse a list enclosed with lower-than and greater-than characters parseLTGT :: Read a => String -> [a] parseLTGT = undefined -- code ommited v =  QuasiQuoter vExp vPat -- In the case of Ints it is simple vExp :: String -> Q Exp vExp str = do let xs = (readLTGT str) :: [Int]                       sanityCheck xs                       [| MkVec xs |] Unfortunately, we cannot implement vExpr in the general case. Removing the explicit signature of readLTGT would lead to ambiguous-type-variable errors. Maybe things would be different if TH's AST wasn't untyped (i.e. vExpr :: String -> Q (Exp a)) I'm not sure if it is feasible, though. I would love to be proven wrong and read about a workaround/solution. Any suggestions? Cheers, Fons _______________________________________________ template-haskell mailing list [hidden email] http://www.haskell.org/mailman/listinfo/template-haskell