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

Quotation Monad #374

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft

Quotation Monad #374

wants to merge 13 commits into from

Conversation

gusty
Copy link
Member

@gusty gusty commented Oct 11, 2020

This will implement #44

A quotation monad allow us to compose functions returning expressions.

At the end of the composition we get a single expression, internally containing markers where an evaluate function needs to run a sub-expression.

Since F# doesn't support the "eval" expression, we can't directly run this expressions in existing quotation evaluators, but we include an Expr.run function which takes any normal quotation evaluator and takes care of handling the internal marker. So, instead of doing evaluator expr we do Expr.run evaluator expr.

@cannorin cannorin self-requested a review October 13, 2020 07:54
Copy link
Member

@cannorin cannorin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I experimented around it a lot and I think I understand why the current implementation looks like this. I think this is one of the best we can have for a "quotation monad", but here is my two cents.

Here, we can't make use of the created Expr<'a> value for anything but executing it, because it contains SpliceExpressions which make the expression illegal and have to be removed (by eval). This makes me wondering how this "monad" can be useful, since I suppose most people would want to use the computation expression to create a valid Expr<'a> value that can be consumed by other libraries (without actually running it), but it isn't possible (this is not a problem in MetaOCaml, since it's all about running the code and there is no API to directly manipulate the AST).

Since a F# code can have side effects anywhere, we can't easily define m >>= f without breaking the semantics. We have to syntactically inspect the f and replace every occurrence of the argument with x (this is not much of a problem in Template Haskell since it uses IO monad so it can be done safely). Luckily we can do this for the computation expression binding let! x = m in body by using [<ReflectedDefinition>] since it is always a lambda abstraction, but this means generic >>= operator and generic monad builder are no more usable for the quotation monad.

So I think we have several options:

  • Wrap the Expr<'a> type (in WrappedExpr<'a>, for example) and make it a monad.
    • Then we define val WrappedExpr.run : (Expr -> obj) -> WrappedExpr<'a> -> 'a.
    • And val WrappedExpr.toExpr : WrappedExpr<'a> -> Expr<'a>. This requires the syntactical replacement described above.
  • Create a specialized builder like quotation { ... } for the purpose described above.
    • We also have to implement the syntactical replacement for this.
    • Then we may or may not make Expr<'a> a monad.
  • Do both of them.
  • Do neither and keep it as is.

Also, I found an interesting paper around this topic: https://www.semanticscholar.org/paper/On-Meta-Programming-and-Code-Generation-in-F-Larjani/ca1a48245a767992f4461fe2e66217e7a4fa83d6

@gusty gusty force-pushed the master branch 2 times, most recently from 32f5c4a to f2d1afd Compare August 30, 2022 17:21
@gusty gusty force-pushed the master branch 4 times, most recently from 5c69948 to 9ca5706 Compare September 19, 2022 15:20
@gusty gusty force-pushed the master branch 2 times, most recently from 5b61ffc to ad56a34 Compare December 2, 2022 10:55
@gusty gusty force-pushed the master branch 4 times, most recently from 5b07481 to 7f93d61 Compare February 21, 2023 14:24
@gusty gusty force-pushed the master branch 10 times, most recently from 105ed2c to d80a4ad Compare February 22, 2023 07:56
@wallymathieu wallymathieu force-pushed the master branch 5 times, most recently from f92d910 to 39638fb Compare February 22, 2023 17:36
@gusty gusty force-pushed the master branch 6 times, most recently from 9b34ece to b2f3c8c Compare October 15, 2023 05:01
@gusty gusty force-pushed the master branch 2 times, most recently from 484cff5 to 142c806 Compare December 18, 2023 08:18
@gusty gusty force-pushed the master branch 6 times, most recently from eef4e98 to f2e49ba Compare September 18, 2024 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants