Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# compare quotations

Tags:

f#

following prints "false"

let e1 = <@@ let d = 1 in d+1 @@>
let e2 = <@@ let d = 1 in d+1 @@>

printfn "%A" (e1 = e2) 

The reason is that Var nodes are compared by pointer reference and not by structural equality. Is there already implemented a way to compare quotations intuitively?

like image 220
Liviu Avatar asked Apr 24 '14 12:04

Liviu


People also ask

How can I recover my Facebook password without code?

To reset your password if you're not logged in to Facebook: Click Forgot Password?. Type the email, mobile phone number, full name or username associated with your account, then click Search. Follow the on-screen instructions.

How can I log into Facebook for free?

Email: You can log in with any email that's listed on your Facebook account. Phone number: If you have a mobile number confirmed on your account, you can enter it here (don't add any zeros before the country code, or any symbols). Username: You can also log in with your username, if you set one up.


1 Answers

There are many reasons why comparing quotations does not "work" by default:

  • Quotations can contain references to values for which comparison may not be defined (e.g. if you create a quotation that captures some .NET object that does not support comparison).
  • Quotations contain information about the location in the source code - so your two quotations are different simply because they are on different lines!
  • There is a question whether you want to treat (fun x -> x) and (fun y -> y) as the same - logically, they are, but syntactically, they are not.

So, if you want to check whether quotations are equal, you'll just have to implement your own check. Something like this does the trick for the basic case you have in the example, but it does not handle all the cases:

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

let rec equal = function
  | Let(v1, ea1, eb1), Let(v2, ea2, eb2) -> 
      v1.Name = v2.Name && equal (ea1, ea2) && equal (eb1, eb2)
  | Var(v1), Var(v2) -> v1.Name = v2.Name
  | Lambda(v1, e1), Lambda(v2, e2) -> v1.Name = v2.Name && equal (e1, e2)
  | Call(None, m1, es1), Call(None, m2, es2) -> 
      m1 = m2 && (List.zip es1 es2 |> List.forall equal)
  | Value(v1), Value(v2) -> v1 = v2
  | _ -> false
like image 90
Tomas Petricek Avatar answered Sep 19 '22 11:09

Tomas Petricek