I'm working on a library to generate SQL from LINQ expressions (basically a modified subset of LINQ-to-SQL). I'm using discriminated unions to model the SQL expressions, but have encountered some (perceived?) limitations. I want to do something like the following (note the last line):
type SqlSourceExpression =
| Table of string
| Join of JoinType * SqlSourceExpression * SqlSourceExpression * SqlExpression //ie, left, right, predicate
and SqlExpression =
| Source of SqlSourceExpression
| OrderBy of SqlExpression * SortDirection
| Select of SqlSourceExpression * SqlExpression * OrderBy list //can't do this
I could do the following:
type SqlOrderByExpression = SqlExpression * SortDirection
...and change the last two lines to:
| OrderBy of SqlOrderByExpression
| Select of SqlSourceExpression * SqlExpression * SqlOrderByExpression list
But that appears to have two problems:
SqlOrderByExpression is not a SqlExpression. This makes it hard to use the visitor pattern (maybe herein lies the problem?). Which means when traversing a Select expression I can't iterate over the list of order by expressions passing each one to Visit(expr:SqlExpression).
SqlOrderByExpression is merely a type alias for a tuple, so no type information is preserved. That hurts readability IMO.
Is there a better way to model this? I tried the inheritance route, but I think DUs are MUCH easier to work with (barring the noted difficulty).
As you work with FP technique (DU), as you don't need to remember OOP patterns, just use high-order functions (fold, map, zippers, etc).
In case you just want to specific view for your matching code, there is active patterns:
let (|OrderByTerm|OrderByList|_|)= function
|OrderBy x -> Some (OrderByTerm x)
|Select (_,_,xs) -> Some (OrderByList xs)
|_ -> None
I'm not sure why SqlExpression, as a discriminated union, has cases for OrderBy and Select. What's allowed to go inside an OrderBy?
I think discriminated unions are making this more difficult than it needs to be. I think SqlSourceExpression, SqlOrderByExpression and SqlSelectExpression can be different types. You can make them records if you're worried about tuples being difficult to read (this is what I'd do in your situation).
I think an SqlExpression discriminated union will come in useful when you start to represent expression trees like (1 + SUM(ISNULL(Value1, Value2))) / COUNT(*), where the syntax is more flexible.
Related
What does type X = Y of Z mean in F#? In particular, does the Y token have any material purpose? If I want to express the fact that X is a type backed by the underlying type Z, why do I need Y in that expression?
According to https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/keyword-reference, the of keyword is used to express one of these:
Discriminated Unions
Delegates
Exception Types
Strictly speaking, according to the docs, type X = Y of Z doesn't fall into ANY of the above 3 categories.
It's not Discriminated Union syntax because it's lacking the pipe | character.
It's not a Delegate, because the delegate keyword is absent.
It's not an Exception Type because the exception type is absent.
So it seems like type X = Y of Z is invalid syntax even though it is used pervasively in https://fsharpforfunandprofit.com/posts/conciseness-type-definitions/. Very puzzling - is it that the docs are inaccurate?
Contrary to your intuition, such declaration is, in fact, a discriminated union - one with just one case. Yes, discriminated unions with only one case are totally legal and are sometimes used for type safety or for hiding implementation details.
If you don't want to have that extra Y in there, that is also legal:
type X = Z
This is called "type alias". Its advantage over discriminated union is resource consumption (both performance and memory), but its drawback is that it doesn't provide any extra safety, because X ends up being equivalent and interchangeable with Z in all contexts.
It's not Discriminated Union syntax because it's lacking the pipe | character.
It's possible to omit the first pipe in a Discriminated union:
type DU = A of int | B
This is bad style for standard multi-line definitions but can be appropriate for one-liners. In your example there is only one case so it is possible to omit the pipe completely, which admittedly causes confusion. It would improve clarity to include the bar: type X = | Y of Z
In type X = Y of Z, does the Y token have any material purpose?
Y is used to disambiguate between cases, and for matching against data. If there are are likely to be more cases in future then it makes sense to have this scaffolding for matching. If you know that there will only ever be one case then a DU is not the most appropriate type, since a record type X = { Y: Z } is a simpler construct which achieves the same purpose.
I am creating a simple DSL with multiple discriminated unions(DU) . There is building block DU and higher DUs are build on top of lower ones.
Now I want to create UI where user can build a text which matches my DSL. to UI I don't want to express my full grammar, but show only possible actions that can be done. So I need a way to figure out from my hierarchical DU, what are other possible states that user can do.
sample input text (1 + (2 * 3))
type Expression =
| Constant of int
| Add of Expression * Expression
| Mul of expression * Expression
so when user starts, I have to return a list saying only Constant can be used.
when user passes (constant ) as his current state, I have to tell you can add/Mul (which is expression) and so on.
I want to represent a structure which says, current state and possible states to go from in a type safe way. Is there a way to solve this kind of problem in f#
I think you're looking for FSharpType.GetUnionCases. You can use this as follows:
open System
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Reflection
type Expression =
| Constant of int
| Add of Expression * Expression
| Mul of Expression * Expression
typeof<Expression> |> FSharpType.GetUnionCases|> Dump |> ignore
LinqPad for the above here
I'm want to create a method which would construct an equivalent of query { ... } computation expression (using FSharp.Data.TypeProviders with either LINQ2SQL or LINQ2Entities) from provided data structure, i.e.:
Collection("customers", [
Field "customerId";
Collection("orders", [
Field "orderId" ]) ])
For that I need to understand how the query is translated into code on the first place. Given following query as an example:
query {
for c in db.Customers do
select (c.CustomerID, query {
for o in c.Orders do
select o.OrderID
} |> Seq.toList)
}
What would it look like without computation expression syntax?
I would not recommend generating F# queries programmatically.
The main purpose of queries is to make it possible to write nicely looking F# source code. When they are executed, the code you write is first translated to LINQ-style expression tree, which is then translated to SQL query. If you managed to translate your query specification into F# query, you'd have something like:
+------------+ +----------+ +----------------------+ +-----+
| Your query | -> | F# query | -> | LINQ expression tree | -> | SQL |
+------------+ +----------+ +----------------------+ +-----+
There is nothing wrong with multiple transformations, but there is a number of things that make the path via F# query more complicated:
In your query format, things seem to be represented as strings. So, you'd need to go from strings to .NET MethodInfo just to go back to strings.
With F# queries/LINQ, you get back typed objects and that's one of the main benefits, but if you build query dynamically, you'll just get back a squence of obj values - and will have to use reflection or something like that to access them.
TL;DR - I think it will be much easier to just take your query representation and generate SQL directly. The structure of the transformation is similar to generating F# query, but you won't have to mess around with quotations and reflection.
If you want to see how something desugars, just put it into a quotation. If you do this with your example, you'll see that
<#
query {
for c in db.Customers do
select (c.CustomerID, query {
for o in c.Orders do
select o.OrderID
} |> Seq.toList)
}
#>
is roughly equivalent to
query.Run
<# query.Select(query.For(query.Source db.Customers,
fun c -> query.Yield c),
fun c ->
c.CustomerID,
query.Run <#
query.Select(query.For(query.Source c.Orders,
fun o -> query.Yield o),
fun o -> o.OrderID) #>
|> Seq.toList) #>
(where I've cleaned up a few extraneous variables). I agree with Tomas that there are probably better ways to achieve what you want than trying to create such an expression directly.
I have a function of the form
'a -> ('a * int) list -> int
let rec getValue identifier bindings =
match bindings with
| (identifier, value)::tail -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
I can tell that identifier is not being bound the way I would like it to and is acting as a new variable within the match expression. How to I get identifier to be what is passed into the function?
Ok! I fixed it with a pattern guard, i.e. | (i, value)::tail when i = indentifier -> value
but I find this ugly compared to the way I originally wanted to do it (I'm only using these languages because they are pretty...). Any thoughts?
You can use F# active patterns to create a pattern that will do exactly what you need. F# supports parameterized active patterns that take the value that you're matching, but also take an additional parameter.
Here is a pretty stupid example that fails when the value is zero and otherwise succeeds and returns the addition of the value and the specified parameter:
let (|Test|_|) arg value =
if value = 0 then None else Some(value + arg)
You can specify the parameter in pattern matching like this:
match 1 with
| Test 100 res -> res // 'res' will be 101
Now, we can easily define an active pattern that will compare the matched value with the input argument of the active pattern. The active pattern returns unit option, which means that it doesn't bind any new value (in the example above, it returned some value that we assigned to a symbol res):
let (|Equals|_|) arg x =
if (arg = x) then Some() else None
let foo x y =
match x with
| Equals y -> "equal"
| _ -> "not equal"
You can use this as a nested pattern, so you should be able to rewrite your example using the Equals active pattern.
One of the beauties of functional languages is higher order functions. Using those functions we take the recursion out and just focus on what you really want to do. Which is to get the value of the first tuple that matches your identifier otherwise return -1:
let getValue identifier list =
match List.tryFind (fun (x,y) -> x = identifier) list with
| None -> -1
| Some(x,y) -> y
//val getValue : 'a -> (('a * int) list -> int) when 'a : equality
This paper by Graham Hutton is a great introduction to what you can do with higher order functions.
This is not directly an answer to the question: how to pattern-match the value of a variable. But it's not completely unrelated either.
If you want to see how powerful pattern-matching could be in a ML-like language similar to F# or OCaml, take a look at Moca.
You can also take a look at the code generated by Moca :) (not that there's anything wrong with the compiler doing a lot of things for you in your back. In some cases, it's desirable, even, but many programmers like to feel they know what the operations they are writing will cost).
What you're trying to do is called an equality pattern, and it's not provided by Objective Caml. Objective Caml's patterns are static and purely structural. That is, whether a value matches the pattern depends solely on the value's structure, and in a way that is determined at compile time. For example, (_, _)::tail is a pattern that matches any non-empty list whose head is a pair. (identifier, value)::tail matches exactly the same values; the only difference is that the latter binds two more names identifier and value.
Although some languages have equality patterns, there are non-trivial practical considerations that make them troublesome. Which equality? Physical equality (== in Ocaml), structural equality (= in Ocaml), or some type-dependent custom equality? Furthermore, in Ocaml, there is a clear syntactic indication of which names are binders and which names are reference to previously bound values: any lowercase identifier in a pattern is a binder. These two reasons explain why Ocaml does not have equality patterns baked in. The idiomatic way to express an equality pattern in Ocaml is in a guard. That way, it's immediately clear that the matching is not structural, that identifier is not bound by this pattern matching, and which equality is in use. As for ugly, that's in the eye of the beholder — as a habitual Ocaml programmer, I find equality patterns ugly (for the reasons above).
match bindings with
| (id, value)::tail when id = identifier -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
In F#, you have another possibility: active patterns, which let you pre-define guards that concern a single site in a pattern.
This is a common complaint, but I don't think that there's a good workaround in general; a pattern guard is usually the best compromise. In certain specific cases there are alternatives, though, such as marking literals with the [<Literal>] attribute in F# so that they can be matched against.
F# keyword 'Some' - what does it mean?
Some is not a keyword. There is an option type however, which is a discriminated union containing two things:
Some which holds a value of some type.
None which represents lack of value.
It's defined as:
type 'a option =
| None
| Some of 'a
It acts kind of like a nullable type, where you want to have an object which can hold a value of some type or have no value at all.
let stringRepresentationOfSomeObject (x : 'a option) =
match x with
| None -> "NONE!"
| Some(t) -> t.ToString()
Can check out Discriminated Unions in F# for more info on DUs in general and the option type (Some, None) in particular. As a previous answer says, Some is just a union-case of the option<'a> type, which is a particularly common/useful example of an algebraic data type.
Some is used to specify an option type, or in other words, a type that may or may not exist.
F# is different from most languages in that control flow is mostly done through pattern matching as opposed to traditional if/else logic.
In traditional if/else logic, you may see something like this:
if (isNull(x)) {
do ...
} else { //x exists
do ...
}
With pattern matching logic, matching we need a similar way to execute certain code if a value is null, or in F# syntax, None
Thus we would have the same code as
match x with
| None -> do ...
| Some x -> do ...