tags:

views:

233

answers:

4

Reflector currently added F# but its not work fine, is it possible to use reflection for F#, if not why? I read this. It was for 2008, but if you check some code like bellow in ildasm you can't see anything about Units of Measure.

// Learn more about F# at http://fsharp.net

[<Measure>] type m
[<Measure>] type cm

let CalculateVelocity(length:float<m> ,time:float<cm>) =
    length / time

The ildasm output:

.method public static float64  CalculateVelocity(float64 length,
                                                 float64 time) cil managed
{
  // Code size       5 (0x5)
  .maxstack  4
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  div
  IL_0004:  ret
} // end of method Program::CalculateVelocity

So there are somethings cannot be reflected in F# is it or not? see the comment : Units actually don't get seen at all by the CLR ... in the article.

+2  A: 

You can use Reflection in F#.

As for why Reflector is not working correctly, I'd suggest contacting Red Gate's Support.

Reed Copsey
+2  A: 

You can:

.NET and F# Reflection

The F# library also extends the .NET System.Reflection to give additional information about F# data types

Source

ChrisF
thanks I'll read this document.
SaeedAlg
@SaeedAlg - the bit about reflection starts half way down the page.
ChrisF
+1  A: 

Units of Measure is just a compile-time thing, it doesn't exist in the assembly/CLR.

From part one:

Units-of-measure are not just handy comments-on-constants: they are there in the types of values, and, what's more, the F# compiler knows the rules of units.

dalle
They do exist in the assembly, but they're encoded in a resource rather than in members' signatures. See Tomas's answer for a demonstration that units can be recovered at runtime.
kvb
+10  A: 

As others already pointed out, when you need to get some information about compiled F# types, you can use standard .NET reflection (System.Reflection) and F# reflection which provides information about discriminated unions, records, etc. (Microsoft.FSharp.Reflection).

Unfortunatelly, information about units of measure cannot be accessed using any of these two APIs, because they are checked only during the compilation and do not actually exist at runtime (they cannot be represented in the CLR in any way). This means that you'll never be able to find out whether e.g. a boxed floating point value has some unit of measure...

You can get some information about units of measure using Metadata namespace from F# PowerPack. For example, the following prints that foo is a unit:

namespace App
open System.Reflection
open Microsoft.FSharp.Metadata

[<Measure>] 
type foo

module Main = 
  let asm = FSharpAssembly.FromAssembly(Assembly.GetExecutingAssembly())
  for ent in asm.Entities do
    if ent.IsMeasure then
      printfn "%s is measure" ent.DisplayName

This reads some binary metadata that the compiler stores in compiled files (so that you can see units when you reference other F# libraries), so you should be able to see informaiton about public API of F# libraries.

Tomas Petricek
Thanks to u, excellent answer :)
SaeedAlg