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

Support for TypeProvider nested types with static parameters #88

Closed
JasonKleban opened this issue May 10, 2016 · 4 comments

Comments

@JasonKleban
Copy link

commented May 10, 2016

Can we please track support for TypeProviders providing nested types with static parameters? It seems to me it would be valuable for metaprogramming similar to how static parameterized method support is valuable compared to the language without them. It would allow a fluent-like construction of types and partially make up for the non-variable length static parameters on a single type. Is there a complicated reason that nested parameterized types cannot be supported?

You wrote "Things generally get very nasty when you have a primary set of static parameters on a type" but I'm not sure whether this refers to this support which I'm asking about. I think you're just saying that a statically-parameterized method returning a type dependent on its parameters can get complicated to think about.

An example: Internal DSLs for defining types from other languages can take advantage of the nesting type provision to label different components that aren't clearly delineated in the source language. In this example of a fictitious type provider using this fictitious feature, the Extend schema definitions can be split up as shown but could just as well be combined for defining the types in the domain, but the RequireZero domain invariant specifications which communicate individual domain invariants can need multiple statements and could not clearly be delineated in the source language without comments or manifest files referencing other files or something obnoxious like that.

type myDomain = 
    EmptyDomain
    .Extend<"CREATE TABLE Customers ...">
    .Extend<"CREATE TABLE Charges ...">
    .RequireZero<"SELECT ...", "Rule 1", "Customers may not share an email address with more than 3 other Customers.">
    .RequireZero<"SELECT ... INTO @Intermediate; SELECT TOP 1 1 FROM @Intermediate", "Rule 2", "A Customer's Charges may not total more than the Customer's CreditLimit.">

let updateCustomerName custId name= 
    myDomain.OpDefine<"UPDATE Customer SET Name= @fullname WHERE Id = @Id">(name, custId)
let updateCustomerEmail custId address = 
    myDomain.OpDefine<"UPDATE Customer SET Email = @email WHERE Id = @Id">(address, custId)
let addCharge custId amount description = 
    myDomain.OpDefine<"INSERT INTO Charges ...">(custId, amount, description)
let chargeEverybody amount description = 
    myDomain.OpDefine<"INSERT INTO Charges (...) SELECT @amount, @desc FROM Customer">(amount, description)
let adjustLimit custId delta= 
    myDomain.OpDefine<"UPDATE Customer SET CreditLimit = CreditLimit + @delta WHERE Id = @Id">(delta, custId)

updateCustomerEmail 2823 "Jim Smith" // Emits only the original update - no rules are possibly violated
updateCustomerEmail 2823 "no@thanks.com" // Emits the original update plus some assertion sql for Rule 1 because of potential impact
adjustLimit 2823 -500.00 // Emits the original update plus some assertion sql for Rule 2 because of potential impact
addCharge 2823 630.00 "Oculus Rift" // Emits the original update plus some assertion sql for Rule 2 because of potential impact
chargeEverybody 5.00 "Membership Fee" // Emits the original update plus some assertion sql for Rule 2 because of potential impact

// analysis and embellished sql scripts are generated at compile time.  Type safe sql statement 
// parameterization included.  Domain invariants are enforced.  Can also generate and use 
// deployed stored procs for the benefit of compiled execution plans.

The current alternative is type myDomain = Domain<"CREATE TABLE Customers ... CREATE TABLE Charges ...", "SELECT ... -- RESERVED_DELIM SELECT ... INTO @Intermediate; SELECT @Intermediate"> but this is inconvenient, even if the literal script were instead a file with those contents.

@dsyme

This comment has been minimized.

Copy link
Contributor

commented Jun 2, 2016

@JasonKleban Thanks for the extensive writeup. For now this should really be added to http://fslang.uservoice.com.

My main follow-up question is if you can get the effect you want purely through provided parameters on methods?

@JasonKleban

This comment has been minimized.

Copy link
Author

commented Jun 2, 2016

can get the effect you want purely through provided parameters on methods?

@dsyme - I don't think so - this example translates parameterized sql into function parameters. To gain type safety for those operations, this information needs to be available at compile-time and be part of the types.

@JasonKleban JasonKleban closed this Jun 2, 2016

@dsyme

This comment has been minimized.

Copy link
Contributor

commented Jun 2, 2016

@JasonKleban Thanks - can you add a link to the UV request please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.