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 <xs> -- 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<xs>|] -> 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
participants (1)
-
Alfonso Acosta