hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Tomas Petricek - F# blog

F# - Simple quotations transformation

This article describes very simple code that I wrote while learning how to work with the F# quotations library. Using the F# quotations you can get tree representation of the quoted expression. This allows you to write code that takes code written in F# as data and performs some code analysis or compiles/translates that code to different language. This is very similar to the new C# 3.0 expression trees where you can get expression tree from lambda expression and translate this tree for example to SQL (using DLINQ). However expression trees in C# 3.0 are very limited when compared with F# quotations, so that's one of the many reasons why F# is interesting language.

Introduction to F# quotations

If you want to see how F# represents some expressions you can try it in the FSI (F# interactive). First you need to open three modules that contain functions for working with quotations:

open Microsoft.FSharp.Quotations;;
open Microsoft.FSharp.Quotations.Raw;;
open Microsoft.FSharp.Quotations.Typed;;

Now you can see the internal representation of quotations by writing quoted expression (In VS.Net you can select code and hit Alt+Enter to sent selected code to F# interactive).

<@ 1 + 2 @>

val it : int expr
  = <@ 
      Microsoft.FSharp.MLLib.Pervasives.op_Addition (Int32 1) (Int32 2)
     @>  

One more example with two operators:

<@ 1 + 10/5 @>

val it : int expr
  = <@ 
      Microsoft.FSharp.MLLib.Pervasives.op_Addition (Int32 1)
        (Microsoft.FSharp.MLLib.Pervasives.op_Division (Int32 10) (Int32 5))
     @>

It is not difficult to understand that addition in the first example is represented as function call (function application in the terminology of functional languages) where the function is op_Addition operator and parameters are two integers. This is actually little simplification, because in functional programming you should look at this code as two function applications. The first application binds first parameter of op_Addition to 1 and the result is again function. The second application uses the function returned by the first application and passes 2 as parameter. You can look at F# quotations using both approaches and in the rest of the article I will use the first one.

To demonstrate how to work with F# quotations I decided to write simple transformation of limited mathematical expressions from F# quotations to my data type. The discriminated union that I'm using as target of transformation is similar to the union in F# source file VS.Net template (as you can see it supports only four most basic mathematical operations and all values are stored as integers):

type simple_expr =
  | Int of int
  | Add of simple_expr * simple_expr
  | Sub of simple_expr * simple_expr
  | Mul of simple_expr * simple_expr
  | Div of simple_expr * simple_expr;;

Printing and evaluation of this structure is simple, so I won't describe these here. If you want to look at these functions see attached source code. (function for evaluation is part of VS.Net template too).

Working with quotations

Finally, let's do the interesting part :-). As I mentioned you can get quotations using <@ ... @>. When you want to perform analysis of quotations you need to get the underlying raw representation using the <@@ ... @@> operators. For decomposing the quoted expression we can use Query functions on the expression families defined in the Raw module. This may sound a bit confusing, but in the simple words - the Raw module contains several values that define language constructs (like constants, variables, function application and others) and you can use these values for matching and decomposing quoted expression. Following code should clear this a bit:

let what_is x =
  match Raw.efInt32.Query x with  
    | Some (_) -> "number";
    | _ -> 
  match Raw.efApps.Query x with  
    | Some (_) -> "application";
    | _ -> 
      "something else...";
	    
// Prints "number"	    
print_string (what_is <@@ 1 @@>);

// Prints "application"	    
print_string (what_is <@@ 1 + 2 @@>);

Now we can start writing function that converts mathematical expression quotation to simple_expr structure. It will be recursive function with similar structure as previous. The first match for conversion of numbers will be simple. In the second match we'll have to do two things. First we'll need to determine what function is applied (whether it is addition, subtraction, etc..) and than we'll have to loop through parameters passed to this function and call the function recursively each parameter.

let rec parse x =
  match Raw.efInt32.Query x with  
    // x contains the number so we can simply return Int(x)
    | Some (x) -> Int(x); 
    | _ -> 
  match Raw.efApps.Query x with  
    | Some (op,args) -> 
    
      // op contains quoted reference to function (operator)
      // so we need to extract name of applied function from it
      let opname = (
        match Raw.efAnyTopDefn.Query op with  
          // operators are top-level definitions so we extract name
          // from 'a' that contains info about the definition
          | Some (a,_) -> let t1,t2 = a.topDefPath in t2
          | _ -> failwith ("Function is not a top level definition.");
        ) in
      
      // Recursively translate arguments to simple_expr 
      // and convert returned list to array
      let av = List.to_array(List.map (fun arg -> parse arg) args) in
      
      // Finally, match the operation name with basic 
      // operator names and return according simple_expr value
      (match opname with
        | "op_Addition"    -> Add(av.(0),av.(1))
        | "op_Subtraction" -> Sub(av.(0),av.(1))
        | "op_Multiply"    -> Mul(av.(0),av.(1))
        | "op_Division"    -> Div(av.(0),av.(1))
        | _ ->
          // some other operation - error
          failwith "Not supported operation");
    | _ -> 
      // something else than efApps and efInt32 - error
      failwith "Not supported construction in expression.";;

As I mentioned, the more interesting part of the code is when the quotation matches with efApps which in our case means that the expression is mathematical operation. From the functional point of view efApps means series of function applications. The result of Query function of efApps is tuple containing expression with information about applied function (operator in our case) and parameters of this application.

For extracting operator name we match the first value with efAnyTopDef which returns information about top-level definitions. Returned structure contains assembly name as well as the function name that we need. In the second step we recursively call parse function to all arguments of operator. Once we know the function name and we have arguments translated to simple_expr, we can return the according simple_expr value.

(Cross-posted from: http://tomasp.net/blog/fsquotations.aspx)

Published Friday, July 07, 2006 2:32 AM by tomasp
Attachment(s): metacalc.zip

Comments

 

Jason Haley said:

July 7, 2006 7:41 PM
 

Don Syme's WebLog on F# and Other Research Projects said:

The F# Hub is a community site at www.hubfs.net, and&amp;nbsp;has been full of interesting posts recently.&amp;nbsp;...
July 8, 2006 6:06 PM
 

My F# Notes said:




Introduction
F# quotations allows you to easily write programs that manipulate with data representation...
October 13, 2006 4:49 PM
 

jdh30 said:

Great article. That's described the F# AST and how you can use quotations to decompose an F# expression into its AST.

I'd like to know how to do the converse: built an AST and evaluate it. For example, can you write a calculator that evaluates the expressions it is given using .NET (i.e. to native code) rather than using a slow eval function as you did here?

Cheers,
Jon.
November 17, 2006 6:17 AM
 

tomasp said:

Thanks for your comment Jon!

Currently there is no standard way (as far as I know) for compiling F# quotations (AST). Building it is not that difficult - you can either compose code quoted using <@ .. @> operator (and some other useful operators) or use ef[something].Make (see http://research.microsoft.com/projects/ilx/fsharp-manual/fslib/Microsoft.FSharp.Quotations.Raw.html for list of all quotation types that can be used).

It would be probably possible to implement compiling F# quotations by converting this "public" representation to internal AST used by F# compiler and invoking the compiler, however I'm not familiar with F# source codes enough to do this. The easier (and a little slower) option is to generate F# source code from F# quotations and compiling it using "fsc" compiler (or using my CodeDomProvider which makes it a bit easier, but internally launches "fsc" too).
November 25, 2006 6:17 PM
 

links for 2007-08-23 « dstelow notes… said:

August 23, 2007 4:49 PM
 

Dj said:

Don't Worry, Be Happy! =)









February 29, 2008 12:40 AM
 

http://cs.hubfs.net/blogs/tomasp/archive/2006/07/07/413.aspx said:

April 7, 2008 7:54 AM
 

Bart Masschelein said:

Very nice article, and it was the first article that gave me a better understanding of quotations. However, since it was also one of my first articles overall, it took me some time to figure out that this code only runs on F# version 1.1.13.8, whereas I am using the latest version, namely F# version 1.9.3.14. And things have changed in between, apparently ;-).

A bit of googling later, I encountered http://cs.hubfs.net/forums/thread/3586.aspx, where Robert answers a quotation related question. And this article, together with Roberts answer made me see the light. What I'm trying to say is that this article, although being what I was looking for, is VERY confusing. A nice compromise would be a rewrite of this article using updated coding, combined with the code generation example of Robert. The purpose of this article, which gives hints at how to create an AST, could be the more advanced example.

Mmm, maybe I should not whine, and give it a shot...

br,
Bart  
April 21, 2008 2:44 PM
 

Links on F# Quotation - TripLeZoNe Technology Playground said:

June 15, 2008 5:02 PM
 

Justin Lee's Technology Blog : Links on F# Quotation said:

June 15, 2008 5:03 PM
 

Website Directory - F said:

January 20, 2009 6:59 PM
 

Links on F# Quotation @ JustinLee.sg said:

August 14, 2009 1:15 AM
 

Sapporo Custom Carpet, Sapporo Parts Japanese Subway System said:

May 20, 2010 10:18 AM
 

450sel Sell, 450sel Video said:

May 20, 2010 10:33 AM
 

197 Pontiac Executive Parts, Executive Sedan Suv Limo said:

May 20, 2010 11:35 AM
 

325e Patch Bmw M3, Supercharger My 325e said:

May 20, 2010 12:21 PM
 

G500 Sale Car 2008 Mercedes Benz, $2500 Used Gmc Savana Cargo Van said:

May 20, 2010 12:30 PM
 

1997 Hyundai Tiburon Aftermarket Parts, 2001 Hood Hyundai Tiburon said:

May 20, 2010 12:48 PM
 

Acura Tl Tail Lights, San Diego Auto Trader Acura Integra said:

May 20, 2010 1:58 PM
 

2002 Subaru Legacy For Sale Keyless Entry, 2000 Subaru Legacy Radiator Hose said:

May 20, 2010 4:13 PM
 

P14 P1500 Sienna Headlight, P15 Gene Observed Cyclin Dependent Kinase said:

May 20, 2010 5:59 PM
 

Ls460 Cost Of, Ls460 Clearance 460l said:

May 20, 2010 8:36 PM
 

Dodge Aries Custom, Aries Parts Buy Dodge Shock Absorber Replacement said:

May 20, 2010 8:43 PM
 

E 250 F450 Aluminum, 2009 Crf450 said:

May 20, 2010 9:27 PM
 

Ford Fairmont Headlight Mercury Zephyr Rear Wheel Drive, Coleman Zephyr Tent Fan said:

May 20, 2010 9:51 PM
 

Classified Listings C2500 For Sale Chevrolet Monte Carlo, Auto Yukon Denali Xl Gmc C25 C2500 Suburban said:

May 20, 2010 10:01 PM
 

Chevrolet Brookwood Episode, Brookwood Replacement Alabama Tenet Healthcare Corporation said:

May 21, 2010 1:08 AM
 

Elantra Gamefaqs, Elantra Led Shark Racing said:

May 21, 2010 1:22 AM
 

D211 Hood, D211 Radiator Nokia said:

May 21, 2010 2:35 AM
 

1996 Ford Bronco For Sale Shelby Gt500, Part 4x4 Early Ford Bronco Disc Brake Conversion said:

May 21, 2010 2:46 AM
 

2500 Sale Classified 2001 Gmc Yukon Xl Onyx Black, Gto Sold Ferrari 250 said:

May 21, 2010 3:57 AM
 

2000 Chevrolet Prizm For Sale Classified, Prizm Auto Parts Catalytic Converter Air Tube said:

May 21, 2010 4:00 AM
 

Manual 2008 535i Bmw 550i, 550i Blub Tail Light said:

May 21, 2010 4:14 AM
 

1970 Tempest Lemans, Used 1966 Pontiac Lemans Dealer said:

May 21, 2010 4:28 AM
 

Comparison Volkswagen Fastback, Review Exponent Fastback said:

May 21, 2010 1:37 PM
 

1999 Honda Odyssey Radiator Catalytic Converter Brake Caliper, 2008 Forum Odyssey Ex said:

May 21, 2010 4:00 PM
 

550 Econoline Super Duty Aftermarket Replacement Headlight Assembly Capa Certified Ford E 450, 2005 Ford F 150 Super Crew Cab Unleaded Fuel said:

May 21, 2010 4:30 PM
 

Sale 1998 Concorde Classified Listings Chrysler Sebring, 1994 Chrysler Concorde Used Parts Wiring Harness Pacifica said:

May 21, 2010 6:41 PM
 

Amazon Volkswagen 412 Brake Pads, 412 Auto Sales said:

May 21, 2010 8:17 PM
 

Logitech G25 Racing Wheel Computing Entertainment System, G25 Prothrombin Time Heparin Therapy said:

May 21, 2010 8:53 PM
 

G20 Discount Sylvania Headlight Bulb Infiniti Qx4, Infiniti Qx4 Truck Parts said:

May 21, 2010 9:36 PM
 

Geo Metro Engine Replacement, Metro Rent Chevrolet G3500 said:

May 21, 2010 9:58 PM
 

Cadillac Minivans, 1951 Cadillac Convertible said:

May 21, 2010 10:30 PM
 

2500 Oil Tank, P250 Sale Items Innovative Design said:

May 21, 2010 10:48 PM
 

Par20 Fluorescent Accent Lighting, Accent Accessories Bangalore Hyundai Santro said:

May 22, 2010 1:25 AM
 

Ebay Nova Club, 1995 Audi A6 Wagons For Sale Awd said:

May 22, 2010 3:24 AM
 

Isuzu Trooper Cebu, 1992 Isuzu Trooper Edmunds said:

May 22, 2010 4:51 AM
 

Fuel Economy Corvette Z06, 2009 Coupe Corvette Zr1 said:

May 22, 2010 5:04 AM
 

Classic Travel Hilton Head, 1969 B Classic B Cars Plymouth Road Runner said:

May 22, 2010 7:31 AM
 

Mini Dehumidifier Dry Edv300 Mold Mildew, V30 Guide said:

May 22, 2010 8:25 AM
 

2005 Sale Used Ford Mustang, 05 Mustang Body Kits said:

May 22, 2010 8:42 AM
 

C5 C1500 Area Used 1999 Chevrolet Suburban, K15 C1500 Pickup Coolant Core Size said:

May 22, 2010 9:00 AM
 

2001 I30 Aftermarket Radiators Infiniti Fx45, Collinge I30 said:

May 22, 2010 9:14 AM
 

F10 Value Bmw 5 Series, F10 Rent Islamabad Crescent Plaza said:

May 22, 2010 11:29 AM
 

1968 Mercury Marquis Colony Park, 1988 Radiator 1986 Mercury Grand Marquis Colony Park said:

May 22, 2010 11:51 AM
 

262 Headlight Education, 262 said:

May 22, 2010 12:14 PM
 

C55 Amg Repair Find, Konica Bizhub C550 Manual said:

May 22, 2010 2:53 PM
 

G20 Summit 2006 Protests, Artists Prints For Sale said:

May 22, 2010 2:54 PM
 

Cimarron Aftermarket Headlights Cadillac Owners, Oldsmobile Firenza Cadillac Cimarron Cutlass Calais said:

May 22, 2010 4:17 PM
 

2000 Chevrolet Chevy Prizm Parts Catalytic Converter Exhaust Manifold, 1997 Geo Prizm Firing Order said:

May 22, 2010 4:30 PM
 

B250 Part New Dodge, B2500 Replacement Hq Mazda B2600 said:

May 22, 2010 6:16 PM
 

Lexus E63 Amg Part Rack And Pinion Steering, E55 Sheet Music E63 Amg said:

May 22, 2010 7:44 PM
 

Excelsior Cooling System, Buy Hyundai Excel Body Kits Tail Lights said:

May 22, 2010 7:58 PM
 

Gmc Caballero Parts Accessories Replacement Headlight Assembly, Caballero Order - 344.mfbattle.com said:

May 22, 2010 8:54 PM
 

01 Explorer Accessories, Part Accessories Ford Explorer Floor Mats Cargo Liner - 285.animejin.com said:

May 22, 2010 9:21 PM
 

2007 Toyota Matrix Performance Interior, Matrix Car Toyota Venza - 412.codebluehacks.org said:

May 22, 2010 10:12 PM
 

Discount 745i Bmw 750li Rims, 750li Forum - 179.unlockiphone30.net said:

May 22, 2010 11:06 PM
 

1992 Mitsubishi Mighty Max Map, Mitsubishi Starion Radiator Replacement - 11.tgrconversions.com said:

May 23, 2010 2:02 AM
 

Used Bmw 745i Parts For Sale Steering Gear, Arcuri Sport Bmw E30 - 145.unlockiphone30.net said:

May 23, 2010 2:16 AM
 

M Audio Nova Specifications Mesh Grille, Champagne Supernova Rent - 491.tvshowzone.com said:

May 23, 2010 4:42 AM
 

Mercedes Benz 450slc Manual Power Steering Pump, 450slc Back Up Wamp - 239.tvshowzone.com said:

May 23, 2010 6:10 AM
 

T1000 Buy Save Francotyp Postalia, Sale Classifieds Pre Owned Pontiac T1000 - 46.akemet.com said:

May 24, 2010 4:12 AM
 

1200 Custom, New Ram Dell Inspiron 1200 - 137.myipgirl.com said:

May 24, 2010 4:27 AM
 

F 100 Pickup Aftermarket Body Parts Store Galaxie 500, V21 Aftermarket Engine - 35.1fh.org said:

May 24, 2010 5:50 AM
 

1967 Chevrolet C20 Pickup 5.4 L Fit, Chevrolet C20 Pickup Discount Side Marker Silverado 2500 - 38.ja3ra.com said:

PingBack from http://38.ja3ra.com/
May 24, 2010 6:20 AM
 

Sl320 Chevrolet, Sl320 Cooling System Parts Mercedes - 322.mfbattle.com said:

May 24, 2010 6:55 AM
 

142 Snowboarding Gear, 142 2005 Document - 109.eumreborn.com said:

May 24, 2010 7:09 AM
 

V1500 Suburban Part Number Mitsubishi Fuso, V1500 Girl Used - 479.luna-atra.net said:

May 24, 2010 9:06 AM
 

Used Mercedes Benz Cls Class Cls55, Buy Cls55 Amg Low Disc - 433.jeepsunlimted.com said:

May 24, 2010 10:55 AM
 

Surefire C2 Centurion Tactical, 2005 Centurion Enzo - 389.mfbattle.com said:

May 24, 2010 11:15 AM
 

Mkx Bulb H11 Lexus Gx470, Mkx Cell - 410.zapstreaming.com said:

May 24, 2010 1:47 PM
 

V90 Wholesale Antenna Mast Mtc, V90 Aftermarket Sites Volvo S90 - 275.dlmreza.net said:

May 24, 2010 11:32 PM
 

Clk320 Treatment Class, Clk320 2000 Mercedes Benz Clk Class Sale Used - 76.animejin.com said:

May 25, 2010 4:01 AM
 

G25 G2500 Party Van Rally, Chevrolet G2500 Replacement List Above - 273.renters.ws said:

May 25, 2010 9:57 AM
 

Windstar Price Description, Windstar Removal Repair - 132.jordanbrandallamerican.com said:

May 25, 2010 10:54 AM
 

2008 Lancer Dodge Dakota, Dodge Dakota Rear Window Regulator - 372.tvshowzone.com said:

May 25, 2010 12:39 PM
 

Jeep Compass Sale Milwaukee Bucket Seats, Jeep Compass Removal Chrysler - 223.unlockiphone30.net said:

May 25, 2010 5:18 PM
 

Our Front Plymouth Pb300, Wales Pb300 Replacement - 255.codebluehacks.org said:

May 25, 2010 7:56 PM
 

2009 - 1980 @ Scrambler Bulb, Polaris Scrambler Headlight Bulb Arctic Cat - 255.computeronlinebingo.com said:

May 27, 2010 7:08 AM
 

1981 - 1996 @ Summit Ada Refrigerator, 2005 Ski Doo Summit 800 144 Specs - 466.codebluehacks.org said:

May 30, 2010 5:29 PM
 

2009 - 2000 @ 46v3000 Suburban Chevy, V30 Cell - 405.computeronlinebingo.com said:

May 30, 2010 7:19 PM
 

2009 - 2008 @ Free Lx470 2006 Lexus, Lexus Lx470 Auction Certificate Of Destruction - 479.rkwrh.com said:

May 31, 2010 11:48 AM
Anonymous comments are disabled

This Blog

Post Calendar

<July 2006>
SuMoTuWeThFrSa
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

Syndication

Powered by Community Server, by Telligent Systems