[GHC] #13608: Expose the type of quasiquotes

GHC ghc-devs at haskell.org
Wed May 31 18:42:53 UTC 2017


#13608: Expose the type of quasiquotes
-------------------------------------+-------------------------------------
        Reporter:                    |                Owner:
  facundo.dominguez                  |  facundo.dominguez
            Type:  bug               |               Status:  patch
        Priority:  normal            |            Milestone:
       Component:  Template Haskell  |              Version:  8.0.1
      Resolution:                    |             Keywords:  QuasiQuotes
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  12778             |  Differential Rev(s):  Phab:D3610
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by facundo.dominguez):

 I don't submit a GHC proposal yet because we don't have yet a good
 solution to propose, we only have a problem and a couple of leads to
 investigate.

 I state the problem here in a general form. An account that Mathieu did a
 while ago can be found in ticket:12778#comment:8.

 Template Haskell quasiquotes allow to embed other languages in Haskell
 programs.
 One can use this ability to generate and compile code in a foreign
 language and
 then have the result invoked from Haskell.

 For quasiquotations to be typesafe though, the implementation of the
 quasiquoter
 needs to tell the foreign compiler which types are expected of the
 antiquoted
 variables and of the returned value. Quasiquoters currently have no way to
 find
 the expected return type if the programmer does not supply it explicitly.

 Let's consider the following example using inline-java. The package
 `inline-java`
 implements a quasiquote which allows to embed fragments of Java programs
 in
 Haskell modules.

 {{{
 jappendWorld :: Text -> IO Text
 jappendWorld = [java| $x + " World!" |]
 }}}
 This generates some Java code that is compiled by a Java compiler. It also
 generates some Haskell code which marshals values between Java and Haskell
 and
 invokes the result of compiling the Java code.

 The java code that is generated looks like
 {{{
     class ClassFreshName {
         public static Object freshName(String x) {
             return x + " World!";
         }
     }
 }}}
 The quasiquoter knows that the antiquote `x` has type `String` in Java,
 because
 it knows that `x` has the type `Text` in Haskell and it can marshal the
 values
 between the two types. The quasiquoter can find the Haskell type of `x`
 via the
 Template Haskell function `reify` as implemented in ticket:11832.

 However, the quasiquoter has currently no way to find the expected return
 type.
 Therefore, it assumes that any return value is of the catch-all Java type
 `java.lang.Object`. This is problematic, because it is up to the
 programmer
 to use the return value in a way appropriate to its type. If the value
 returned
 by the quasiquote does not match the type expected by the programmer on
 the
 Haskell side, the program has undefined behavior.

 Solutions:

 1. Have the programmer supply the return type, this is how the package
 `inline-c`
   works to embed `C` programs in Haskell. This involves effort on the part
   of the user to write the return type in every quasiquotation.

 2. Use typed splices instead of quasiquotes. e.g.

    {{{
       $$(java [string| $x + " World!" |])
    }}}

    Typed splices do expose the expected type to the implementation, and
 the generated code
    could be tailored by using type classes. This is rather clumsy to write
 while
    quasiquotes are the best fit.

 3. Implement typed quasiquotes, so we can write

    {{{
        [java|| $x + " World!" ||]
    }}}

    which desugars to

    {{{
        $$(typedQuoteExp java " $x + \" World!\")
    }}}

 4. What this ticket proposed.

 5. Similar to (4), but avoid introducing a name with a hash of the
 location.
    For this, we extend the type checker so when it finds a splice, it adds
 a
    binding to the typing environment which has the type of the splice and
 an
    identifier uniquely associated to the splice. Calls to `reify` can then
    find this binding and yield the type in the same fashion that it is
 done
    with antiquoted variables.

 Let me know if this should still be sent to GHC proposals. Besides that,
 any thoughts or advice?

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13608#comment:12>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list