Pages

Tuesday, March 27, 2012

Self-Note: Make type provider work in FSX file

When I wrote the type provider using an my own erased type (not system type) and wanted to to test it in the FSX file, I run into an error. What I did is to write my type in a separate DLL and reference that DLL in the FSX file, which is used for testing purpose, and in the type provider file. 

The error I got in the FSX file is: cannot reference to the DLL contains my own type. I double checked the FSX and I did add #r. The real reason behind is the AssemblyLoad context. The type provider code was doing the Assembly.LoadFile in a different load context. The following code should resolve the problem:

    static do
        System.AppDomain.CurrentDomain.add_AssemblyResolve(fun sender anea ->
            let loaded = System.AppDomain.CurrentDomain.GetAssemblies()
            let an = System.Reflection.AssemblyName(anea.Name)
            match loaded |> Seq.tryFind(fun a -> System.Reflection.AssemblyName.ReferenceMatchesDefinition(an, a.GetName())) with
                | Some a -> a
                | None -> null
                )


Sunday, March 25, 2012

F# ≥ C# (ASCII string definition)

When go over the data definition in F#, I found the string ASCII definition in F# which was new to me. The ASCII string uses "B" as suffix and it represent an ASCII string and internally it is a byte[].
let asciiString = "abc"B;
In the C#, I have to do

string value = "abc";
// Convert the string into a byte[]. 
byte[] asciiBytes = Encoding.ASCII.GetBytes(value);

This small syntax sugar would help me a lot when I did some programming targeting to PLC and other hardware.


Friday, March 23, 2012

F# Unit test template is published

No hacking for the F# unit test anymore. I just published the F# unit test template for Visual Studio 11. Now you can create F# unit test project and add new unit test item. You will get something like the following screenshot when you click "Unit Test", "run unit tests", and "All tests".



Personally I have a small library for my own unit test authoring to save some typing when I write my unit testing.  Feel free to leave comment.

Be sure to make your test case return "unit", otherwise it won't be recognized as a test case.



F# 3.0 CLIMutable Attribute

If you have ever been working with XAML with some designer support, you will be additive to the benefit brought by designer. I'd spend weeks without implementing any feature and work on designer support. One scenario is described here. Default constructor is the key! Unfortunately, the record type in F# does not have a default constructor by default and it makes binding difficult.

Now we have CLIMutable to solve this problem. The screenshot for CLIMutable is below:

If you define the following F# code:

[ < CLIMutable > ]
type R =
  { X: int; Y:int }
type R2 =
  { X: int; Y:int }

then in the C# code you can do

var x = new R();
var x2 = new R(0, 2);
var y = new R2(0, 2);
// var y2 = new R2();   //does not compile

The type R has the default constructor while R2, which is not decorated with CLIMutable, does not have the default constructor.

Hopefully this 3.0 feature can make your UI work a little easier. :-)


Create Visual Studio 11 Template

Recently I have a task to write a template. The task seems easy but turns out very consuming. It involves little programming, but manual mouse click steps.

Because I cannot find VS SDK 2011, so I have to use VS 2011 SP1 SDK. Follow the following screenshoot, you can create a VSIX project:

This will give us the VSIX project. The content is actually from Visual Studio 11's export feature:

The export template provides a .zip file. Copy this .zip file to the VSIX project. The UI is pretty straightforward, the only problem is the VSIX is only generated for Visual Studio 2010. The way to make the VSIX work for 2010 is to make sure the Visual studio version set to 11.0 in the source.extension.vsixmanifest file. You might have to use notepad to edit the content of the file.

< SupportedProducts >
      < VisualStudio Version="11.0" >

If you ever decide to modify the zip file, please make sure you go to Visual Studio UI remove the content and re-add the content. I have been bitten this badly. :-(

Monday, March 19, 2012

F# 3.0 Automatically Implemented Property

F# 3.0 implements a new feature: Automatically Implemented Property (AIP). This simplifies the property declaration in a type definition, but there are more than that.

The basic AIP is you can define a property with a more concise syntax, the MyProperty below is a AIP.
type MyType() = class
    member val MyProperty = 0 with get, set
end
The property MyProperty will be translated to something like the following:
type MyClass() = class
    val mutable internal MyProperty@ : int
    member this.MyProperty with get() = this.MyProperty@
                                           and set(v) = this.MyProperty@ < - v
    ....
end
From the definition, you will see the there is a back-end field "MyProperty@". As a result, MyProperty@ shows in the class definition when debug the program.

The interesting part for this definition is the 0 in the definition. It is the initial value for the back-end property. If you like to reference to a value outside of the class definition, you can write something like.
let mutable a = 10
type MyType() = class
    member val MyProperty = a with get, set
end
the value from "a" will be taken as initial value for MyProperty. It does not mean MyProperty is a wrapper for "a".

you can make "a" immutable and the code still compile and work.

There are two important notes I have to put with AIP:
  • the back-end field "MyProperty@" does not decorate with "CompilerGenerateAttribute"
  • the object expression does not support AIP.
  • the property's getter and setter always have the accessibility modifier, which is either public or private. You cannot do something like member val MyProperty = 0 with get, private set.
  • Also, you do not put any attribute on the get and set.


Thursday, March 15, 2012

F# ≥ C# (Tuple and Value retrieval)

When I think about the failed type provider, the biggest gain is that I can write something like 


let (Quotations.Patterns.Call(_,eq,_)) = <@ "aa"="b" @>


the equal operation is assigned to "eq". You only care about the "eq", not even need to declare the other parts. I really likes this elegant syntax, you can do:


let (_,b) = (2,3) where b will be 3.


Can you easily do this in C#? Maybe not.. :-)


F# on Windows Phone - Graphic Calculator

During the recent Seattle F# Meetup, I was asked how to do the windows phone calculator with F#. It is not hard provided you know F#.

The backbone of the calculator is a string parser. It can be written from scratch or use existing one. Since I want to get it into production and not prepare for an interview, I choose to use the existing yacc parser provided by F# powerpack. If I hook the back-end yacc parser with the front-end, the majority of the work is accomplished, the rest is to brush your yacc/lex knowledge. I choose use the C# XNA as front-end because I want to draw the function diagram later and am afraid Silverlight won't meet my requirement. You can use F# XNA as front-end, but this is not the main topic.

The whole solution has 4 projects. Two of them are XNA standard projects and two of them are F# ones. The  Calculator folder contains the yacc/lex file. I use the F# Parsed Language Starter to create the project. This project is for desktop application, you have to modify the project file by adding the  the import elements:
  
And XNA project settings:

    

The most important is to make sure the project references the FSharp.Core.dll for Windows Phone.
They are located under the "Dependencies" folder.
If you go to WindowsPhoneCalculator project and find the following line in the Game.cs
    var r = Calculator.readAndProcess("1+3*2");

if you stop at that line, the r is 7. The full code is here.




Wednesday, March 14, 2012

My failure, my experience (Write unit-test type provider)


Some people say the experience is from your failure. They could be wrong in some cases, but it fits my situation. If you read this and gain some experience when writing F# type provider, as a F# team member, I will be very happy. First of all, you have to download the project which can work with VS2011 Beta.

When I realize can write unit test in F#, I was thrilled and wanted to make the syntax more concise as my fingers was strangled when I typed F# attribute on my laptop keyboard. It was long time since I wrote the RegEx type provider, so I jumped onto it before thinking it through. This is the first and fatal mistake for this project. Let me explain it later.

I started to write the type provider interface by taking a DLL file name: (in the test.fsx)

[ < Literal > ]
let tesDll = @"\CodeLibrary.dll"
open Samples.FSharp.UnitTestTypeProvider
type T = UnitTestTyped< tesDll >
Inside the type provider, I can user reflection to get all the types and public methods to generate a wrapper. Everything seems simple and straightforward until I found out the methodInfo cannot be referenced in the invoke code in UnitTestProvider.fs line 76. Instead, it needs a quotation passed into the invoke code.

If this project is a failure, the experience I gain is to use quotation in type provider writing. The following is the way to write quotation and pass it into the invoke code section.

let l = if hasInputs then args.Tail.Tail.Tail else []
let callExpr = Quotations.Expr.Call(args.[1], mi, l )
let (Quotations.Patterns.Call(_,eq,_)) = <@ "aa"="b" @>
let eq = eq.GetGenericMethodDefinition().MakeGenericMethod(mi.ReturnType)
let eqTestExpr = Quotations.Expr.Call(eq, [callExpr; args.[2]])
<@@  if not %%eqTestExpr then failwith "not equal" @@>)

The above code get an equal operator and turn it into a generic method. The final equal operation is created by "MakeGenericMethod" with methodInfo's return type. In this way, we can do a strong type comparison and the performance is better. Everything works perfectly until I realize the erased type provider does not generate a concrete type and cannot insert customized attribute. This is the final blow to this project, as if there is no attribute, all my work is in vain. And also the erased type provider does not have a concrete type which cannot inherit, which seals the fate of this project. Now my project is doomed. :-(

The lesson I learnt is

  • Think the type provider interface first and think it through before started.
  • All the type provider we write with Beta is erased type provider, it does not support attribute decorated on the method
  • Erased type provider is not a concrete type, so inheritance won't work here.

  • quotation is the way to write invoke code. This sample only shows how to make Equal method working in the invoke code, it is not feasible to know all the quotation transforms; however, it definitely opens a door to the new territory. 











Saturday, March 10, 2012

Sample in detail (write unit test)


In the Beta release, we published F# Beta samples. In the sample pack, there is a small one I’d like to dig into detail. Before Beta, hack is the only way to write unit test in F#. This sample was inspired by the recent post by Jack Fox. Why F# is good at unit test, because of its concise syntax and its functional nature. If you vision a function is a way transforming an input sequence to an output sequence, then F# is a perfect way to write unit test for a function.
For convenience, I created the following operators:
let inline (==) a b = Assert.AreEqual(a,b)
            let inline (!=) a b = Assert.AreNotEqual(a,b)
            let inline (===) a b = Assert.AreSame(a,b)
            let inline (?+) a = Assert.IsTrue(a)  //+ stands for TRUE
            let inline (?-) b = Assert.IsFalse(b) //- stands for FALSE
the ?+ and ?- are to test if a value is TRUE or FALSE.
let inline agreeTo sourceFunction targetFunction input =
        let source = input |> sourceFunction
        let target = input |> targetFunction
        let compareFunction a b = if a=b then 0 else -1
        let compareResult = Seq.compareWith compareFunction source target
        if compareResult <> 0 then failwith "sequence not equal"
The compare function is to compare two sequences are equal, the equal comparer is =. You can always add your comparing function to replace the default “=” function.
You can start an F# library project and put the sample code into the moduel1.fs. Because F# does not always specify the return value type, you have to make sure the function return type is F# type unit. If you happen to return something from the function, it won’t be picked up by the testing system. Please be very careful about this, I have been bitten several times and it is very easy to make such mistake in F#.
When everything compiles, you can use “unit test” -> “run unit tests” -> “all tests” to run your unit tests.