Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template PureScript #140

Closed
reverofevil opened this issue Jan 27, 2014 · 4 comments
Closed

Template PureScript #140

reverofevil opened this issue Jan 27, 2014 · 4 comments

Comments

@reverofevil
Copy link

Pros:

  • Allows a lot of powerful techniques needed to work with data (type providers, XML, JSON and SQL interop)
  • deriving directives are the part of the library, one could define some more derivings (for example, Check to generate isNothing, isJusy etc.)

Cons:

  • Typecheck gets trickier
  • Needs update to module system

Tutorial for macros in Scala: http://docs.scala-lang.org/overviews/macros/overview.html

@pkamenarsky
Copy link
Contributor

As a first step, what about a built-in primitive like:

reify :: a -> (AST -> b) -> b

An example:

f = reify (if 1 == 1 then True else False) print

Basically, reify inlines the AST of the first argument into the second argument. Some issues/questions:

  • The reified AST needs to be complete, i.e. free variables need to be recursively inlined. As an alternative, something like a -> (Tuple AST (Map Var AST) -> b) -> b may be good enough, where Map Var AST is the environment of all bindings in scope.
  • Can this be implemented as a simple desugaring step? Should be doable, except when the AST references something from another module. Are all imported modules available when desugaring a module?

The most obvious use case for something like this is sending code over the wire, Erlang-style. Right now this is only possible with some sort of restricted custom DSLs (+ free monads etc), where things like if or case need to be encoded as combinators, losing things like exhaustivity checking in the process.

@pkamenarsky
Copy link
Contributor

So I thought about this a little bit more.

First of all, the type of reify can actually be simplified to forall a. a -> AST.

So when an expression is reified, simply replace reify a with the serialised AST of a. If there are any free variables in a, recursively generate ASTs for those. If a free variable references a Declaration from another module, first resolve that and then continue as above (is this possible with the current module system?)

Furthermore, taint all binders referenced by free variables in a as "reified" and replace their type with something equivalent to (AST, x) for any binder x. When a dependent module calls a function with a tainted argument, reify it and pass the AST along the original value.

I.e:

M1:

value :: Int
value = 1

M2:

f :: (Int -> Int) -> AST
f g = reify (g M1.value)

M3:

test :: Int
test = M2.f (\x -> x * 2)

Now, there are two free variables in the expression passed to reify in M2.f: g and M1.value. M1.value is a declaration in M1, so just generate its AST normally. g references a binder, so taint it (using some simplified AST notation here):

f :: (AST, Int -> Int) -> AST

1: f (gAST, g) = gAST `Abs` reify M1.value
2: f (gAST, g) = gAST `Abs` Lit 1

Now, M3.test calls M2.f. Its first argument is tainted however, so pass along its AST:

test :: Int

1: test = f (reify (\x -> x * 2), \x -> x * 2)

Now continue the process as above, recursively. Since there are no free variables in \x -> x * 2, just generate its AST:

2: test = f (Var x `Abs` (Var x `App` Op "*" `App` Lit 2), \x -> x * 2)

I don't think the type checker needs to be modified for that, because the tainted flag just tells every call site to replace exp with (reify exp, exp). That should be enough.

@srghma
Copy link
Contributor

srghma commented Jul 8, 2018

Why this is closed?

@garyb
Copy link
Member

garyb commented Jul 8, 2018

As per the linked issue #2749, it needs an amount of research and a proper fleshed out proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants