Pages

Sunday, August 19, 2012

F# Extension Methods

The F# extension method is one of my favorite feature in F#.

F# method and property to be used inside F#

F# extension methods for F# is like 
[ < AutoOpen > ]
module ExtensionMethodsOnlyInFSharp =
    type System.String with
        member this.IsFSharp() = this = "F#"
        member this.``IsF#`` with get() = this = "F#"
And it can be invoked like:
    printfn "equal to F#? %A" ("F#".IsFSharp())
    printfn "equal to F#? %A" ("F#".``IsF#``)
The IsF# is a property. So F# can define extension property! 

F# method to be used in C#

The extension method needs for C# needs an attribute. [ < System.Runtime.CompilerServices.ExtensionAttribute > ]

The extension method defined in the F# can be used in C# is like:

[< System.Runtime.CompilerServices.ExtensionAttribute >]
[< AutoOpen >]
module ExtensionMethodForCSharp = 
    [< System.Runtime.CompilerServices.ExtensionAttribute >]
    let IsFSharp(str:string) = str = "F#"

    // not possible to access from C# IDE
    [< System.Runtime.CompilerServices.ExtensionAttribute >]
    let ``IsF#``(str:string) = IsFSharp str

F# extension methods on Array

F# can define the extension method on array generic (without specifying the concrete type for 'T). It is NOT possible to declare extension method for concrete array ,such as float [].

type 'T ``[]`` with
        member this.MyExtension with get() = "my extension"

I just added code snippet support for the extension method. You can find at the codeplex project.

Friday, August 10, 2012

Use Space in F# Namespace and Module

It is Friday's afternoon and sun finally decide to visit Seattle. I decide to have some fun with F#. I tried to use  space in the variable name with ``. It works perfectly and then  I decide to add space to other components like namespace and module.

Result: both namespace and module name can contains space.

But there are some limitation. The C# IDE does not support namespace contains space. As a result, the C# cannot reference the F# function inside a namespace which contains space. Because F# support space, so you can reference function inside F# code.

In File1.fs

namespace A.``My Space``
type MyClass() = class end
In File2.fs, the following code compiles.

module File2
open A.``My Space``
let c = MyClass()
let d = A.``My Space``.MyClass()
Not sure if somebody wants to use this feature to hide the code from C#, but it is do-able.. :-)

Sunday, August 5, 2012

Self Note: Yahoo Finance Tags

Sample to use the following tags:

http://finance.yahoo.com/d/quotes.csv?s=GE+PTR+MSFT&f=snd1l1yr

aAska2Average Daily Volumea5Ask Size
bBidb2Ask (Real-time)b3Bid (Real-time)
b4Book Valueb6Bid SizecChange & Percent Change
c1Changec3Commissionc6Change (Real-time)
c8After Hours Change (Real-time)dDividend/Shared1Last Trade Date
d2Trade DateeEarnings/Sharee1Error Indication (returned for symbol changed / invalid)
e7EPS Estimate Current Yeare8EPS Estimate Next Yeare9EPS Estimate Next Quarter
f6Float SharesgDay’s LowhDay’s High
j52-week Lowk52-week Highg1Holdings Gain Percent
g3Annualized Gaing4Holdings Gaing5Holdings Gain Percent (Real-time)
g6Holdings Gain (Real-time)iMore Infoi5Order Book (Real-time)
j1Market Capitalizationj3Market Cap (Real-time)j4EBITDA
j5Change From 52-week Lowj6Percent Change From 52-week Lowk1Last Trade (Real-time) With Time
k2Change Percent (Real-time)k3Last Trade Sizek4Change From 52-week High
k5Percebt Change From 52-week HighlLast Trade (With Time)l1Last Trade (Price Only)
l2High Limitl3Low LimitmDay’s Range
m2Day’s Range (Real-time)m350-day Moving Averagem4200-day Moving Average
m5Change From 200-day Moving Averagem6Percent Change From 200-day Moving Averagem7Change From 50-day Moving Average
m8Percent Change From 50-day Moving AveragenNamen4Notes
oOpenpPrevious Closep1Price Paid
p2Change in Percentp5Price/Salesp6Price/Book
qEx-Dividend DaterP/E Ratior1Dividend Pay Date
r2P/E Ratio (Real-time)r5PEG Ratior6Price/EPS Estimate Current Year
r7Price/EPS Estimate Next YearsSymbols1Shares Owned
s7Short Ratiot1Last Trade Timet6Trade Links
t7Ticker Trendt81 yr Target PricevVolume
v1Holdings Valuev7Holdings Value (Real-time)w52-week Range
w1Day’s Value Changew4Day’s Value Change (Real-time)xStock Exchange
yDividend Yield

Saturday, August 4, 2012

Type Provider Sample to Perform the Design Time Validation

Let us continue from the type provider samples from the previous post.

If you have not noticed the type provider is actually a design-time feature, the sample here is to highlight this feature. The production code requires the XML meet certain criteria. In this sample, the XML's start value <= end value.

There are several ways to prevent this kind of error:

  1. use schema
  2. use test case
  3. or, leave this to run-time crash.. ;-)

In this case, it is not easy to define this requirement in a schema file. The test case can check this kind error in a brute-force way. Even I do not invoke the code, the test case still runs. I want this kind of validation only happens when the method is used. The ideal situation is to let Visual Studio to tell there is something wrong with the  XML file and prevent you from a successful compilation. I want to bring this kind of run-time error to design time. The production code is listed below.

type MyProductionCode() = class
    member this.Work() =
        let xml = XDocument.Load("XmlFile1.xml")
        let start = xml.Descendants(XName.Get("Start")) | > Seq.head
        let end' = xml.Descendants(XName.Get("End")) | > Seq.head
     
        // if start >= end, something bad will happen
        if Convert.ToInt32(start.Value) >= Convert.ToInt32(end'.Value) then
            failwith "report illegal parameter from runtime"
end

The way to get this done is to put code in the InvokeCode property in the ProvidedMethod. The InvokeCode returns an code quotation and this code quotation is something will be executed at run-time, other code which is not embedded in the code quotation will only executed at design time and it is the place where can play the tricks.

let m = ProvidedMethod(
                            methodName = "Work",
                            parameters = [],
                            returnType = typeof,
                            IsStaticMethod = false,
                            InvokeCode = fun args ->
                                test.Test1(xmlFileName)      //executed at design time to validate the XML file                      
                                < @@ (%%args.[0]:MyProductionCode).Work() @@ >                                  
                            )

The Test1 method will check the XML file and throw exception if the XML is invalid. As a result, a red line will be under the function call in the Visual Studio. An interesting thing for the type provider version versus the test case is that the error only happens the method appears in the code. If user does not intend to invoke the code, there will be no error.

If you can combine this sample with the wrapper sample, you can have a more general version. We are working on the new release of our F# sample pack and eventually all type provider samples will be there.

I will be moving to cloud and data analysis stuff from next week where F# shows more muscle. Please stay tuned.. :-)

Friday, August 3, 2012

Self Note: Type Provider parameters


in the type provider static parameter, if you do:


let name = parameterValues.[1] :?> string;
let name2 = parameterValues.[2] :?> string;
let nameXXX = [| name; name2 |]


and use the NameXXX it works, but


let name = parameterValues.[1] :?> string;
let name2 = parameterValues.[2] :?> string;
let nameXXX = [| parameterValues.[1] :?> string; parameterValues.[2] :?> string |]


does not work and the error message confusing too. The error message says it does not support constant type string[]. It is pretty bad, but you can only get it work using the variable.

[Important] fixed in the recent check in and need latest type provider template.

Two more Type Provider samples

After I have the wrapper sample which insert the logging code, I start to think if there is another way to explore the meta-programming more with type provider. Computer code is also data with schema information and this is something I am more familiar and interested. Another takeaway is the type provider can get information from at least four sources to generate code.
  1. static parameter, such as RegularExpressionTypeProvider<"regular expression pattern">
  2. external source, such as local file or database. One sample is the MiniCSVTypeProvider<"local csv file">
  3. the module which provides variable can also be the source to provide information to generate code. (See first sample)
The sample is a "multi-inheritance" type provider to show how type provider can rearrange the class member and give a better (or different) experience. I am not going to claim the experience is enjoyable for everyone, but at least you have the chance to cook the stuff you like. 

The first and easy to understand sample is here. It create instance of two sealed C# class instance and use type provider to generate provided methods. It seems that the new type is inherit from two sealed class, but actually it is just calling to a wrapper. The C# class is defined as the following. I made them sealed, but this technique works for any class. If the two base class have the function with same name and signature, you will have the liberty to decide how to handle this situation rather than obey the dictation from the compiler.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public sealed class Class1
    {
        public void F1()
        {
            Console.WriteLine("from Class1.F1");
        }

        public void F2()
        {
            Console.WriteLine("from Class1.F2");
        }
    }

    public sealed class Class2
    {
        public void F11()
        {
            Console.WriteLine("from Class2.F11");
        }

        public void F12()
        {
            Console.WriteLine("from Class2.F12");
        }
    }
}

The "multi-inheritance" is achieved by using a wrapper class like:

public class WrapperClass
{
    public Class1 c1;
    public Class2 c2;
    public void F1() { c1.F1(); }
    public void F2() { c1.F2(); }
    public void F11() { c2.F11(); }
   public void F12() { c2.F12(); }
}

The main pain point for this project is write the code quotation, I will have a separate thread to discuss how to write quotation.

The sample code here is to show how to use the Activator.CreateInstance to create two sealed C# class instance and generate a "multi-inheritance" class. This version is the first time I tried to pass the type name into the type provider, the experience, to be honest, is horrible. :-(. I listed here only because it might serve as a general template for some cases and people can use it to find the code quotation they need.

Type provider is really a huge topic when I dig deeper and deeper, hopefully you enjoy it as I do. :)