Polymorphism + Quasiquoting + Untyped AST = problems

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Polymorphism + Quasiquoting + Untyped AST = problems

Bugzilla from alfonso.acosta@gmail.com
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
_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

Re: Polymorphism + Quasiquoting + Untyped AST = problems

Bugzilla from alfonso.acosta@gmail.com
On Wed, Feb 20, 2008 at 8:22 AM, Alfonso Acosta
<[hidden email]> wrote:
>  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 meant

vExp :: String -> Q (Exp (Vec a))

Sorry for the typo
_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

Re: Polymorphism + Quasiquoting + Untyped AST = problems

Bugzilla from alfonso.acosta@gmail.com
In reply to this post by Bugzilla from alfonso.acosta@gmail.com
On Wed, Feb 20, 2008 at 9:12 AM, Geoffrey Mainland
<[hidden email]> wrote:
> On Wed, Feb 20, 2008 at 08:22:18AM +0100, Alfonso Acosta wrote:
>  > Hi,
>  >
>  > Let me show you why I reached that conclusion through a simple example.
>
>  I can't help but feel I've missed some context :)

Well, I'm probably bad at providing simplified examples ;). The real
purpose of using quasiquoters is to help implementing fixed sized
vectors (numerically parameterized lists using type-level numerals).
See http://www.haskell.org/pipermail/haskell-cafe/2008-February/039801.html
for details.


>  > Using "vector" is simple:
>  >
>  > $(vector [1,2,3,4,5])
>
>  Well, not so simple actually, as you'll get an "ambiguous type variable"
>  error unless you add a type signature. For instance:
>
>  $(vector [1::Int,2,3,4,5])

True, I forgot to include the signature. However, even if a signature
is required, vector can still be used to build vectors of any type,
whereas that is not the case when using quasiquoters.

>  The real problem is that you can't splice in a polymorphic
>  variable. Witness:
>
>  v =  QuasiQuoter (fst . vExp) vPat
>
>  vExp :: Read a => String -> (Q Exp, a)
>  vExp str = do let xs = (parseLTGT str) :: [a]
>               sanityCheck xs
>               ([| MkVec xs |], undefined)
>

Yes, I know. I thought it would maybe be possible if TH had a typed AST.
_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell