Question

using let inline and member constraints I'll be able to make duck typing for known members but what if I would like to define a generic function like so:

let duckwrapper<'a> duck = ...

with the signature 'b -> 'a and where the returned value would be an object that implemented 'a (which would be an interface) and forwarded the calls to duck.

I've done this in C# using Reflection.Emit but I'm wondering if F# reflection, quotations or other constructs would make it easier.

Any suggestions on how to accomplish this?

EDIT after reading Tims answer I thought I'd give a bit more details

What I was thinking of when I wrote about using quotations to help was something like:

{new IInterface with member x.SayHello() = !!<@ %expr @>}

!! being an operator translating the quotation to a function and %expr being the unit of work for the method. I'd be able to translate the expression to a function (I guess) but wouldn't know how to

of course this wouldn't do the trick completely either since IInterface would be 'a which is where I hope F# reflection might have some handy functions so that I could construct a type based on a type object and some function values

EDIT As an update to Tomas Petricek answer I'll give some code to explain my needs

type SourceRole =
   abstract transfer : decimal -> context

and context(sourceAccount:account, destinationAccount) =
   let source = sourceAccount
   let destination = destinationAccount

   member self.transfer amount = 
     let sourcePlayer = 
       {new SourceRole with
          member this.transfer amount =
              use scope =  new TransactionScope()
              let source = source.decreaseBalance amount
              let destination = destination.increaseBalance amount
              scope.Complete()
              context(source,destination)
              }
     sourcePlayer.transfer(amount)

which is a try at porting "the" textbook example of DCI in F#. The source and destination are DCI roles. It's the idea that any data object that adhere's to a specific contract can play those. In this case the contract is simple. source needs a memberfunction called decreaseBalance and destination needs a member function called increaseBalance. I can accomplish that for this specific case with let inline and member constraints. But I'd like to write a set of functions that given an interface and an object. In this case it could be source (as the object) and

type sourceContract = 
   abstract decreaseBalance : decimal -> sourceContract

as the type. The result would be an object of type sourceContract that would pipe method calls to a method with the same name on the source object.

Was it helpful?

Solution

You can compile F# quotations using components from F# PowerPack. So I think you could use quotations to generate and execute code at runtime. If you write a quotation representing a function & compile it you'll get a function value that you could use to implement an interface. Here is a trivial example:

#r "FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation

// Create a part using "Expr." calls explicitly
let expr = Expr.Value(13)
// Create a part using quotation syntax 
let expr2 = <@ (fun x -> x * %%expr) @>

// Compile & Run
let f = expr2.Compile()()
f 10

You can mix quotation syntax and calls to Expr, which makes it easier to compose code from basic blocks. The compilation is a bit stupid (currently) so the generated code won't be as efficient as usual F# code (but you'll need to measure it in your case).

I'm not quite sure I understand what exactly are you trying to do, so if you can provide more details, I can give more specific answer.

OTHER TIPS

F# reflection (Microsoft.FSharp.Reflection) is an F#-friendly wrapper around the plain System.Reflection APIs, so I don't think it would add anything here.

Quotations can't define new types: (you'd need to define a new type to do your interface-based duck typing)

> <@ { new IInterface with member x.SayHello = "hello" } @>;;

  <@ { new IInterface with member x.SayHello = "hello" } @>;;
  ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(7,4): error FS0449: Quotations cannot contain object expressions
> <@ type Test() = class end @>;;

  <@ type Test() = class end @>;;
  ---^^^^

stdin(8,4): error FS0010: Unexpected keyword 'type' in quotation literal

Reflection.Emit is still the way to go with this.

Edit:

I hope F# reflection might have some handy functions so that I could construct a type based on a type object and some function values

I'm afraid it doesn't. Here's the documentation on F# reflection: http://msdn.microsoft.com/en-gb/library/ee353491.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top