Pages

Showing posts with label F#. Show all posts
Showing posts with label F#. Show all posts

Sunday, November 11, 2018

Move NLP IKVM to F# .NET-Friendly

Since the last post, I read Sergey's code. Then I decided to work on refactoring the code to store the data into the .NET and F# format. Stanford NLP does provide a server. I still want to make it .Net friendly and also get myself familiar with the NLP core.

I prefer the project-based solution than the interactive solution is because it can have Visual Studio's watch, immediate windows, and debug visualizer. Once I got the information into a comfortable environment, it will be easy to move forward. 

The 200-line code is to build up a structure like the following:

I call multiple sentences a story. A story contains (1) sentences and (2) cross-references. The sentence structure shows NLP info about a sentence. The sentence includes a token list, tree, and dependency graph. The cross-references maintain the relationship among elements from different sentences. The first file is the main file. It shows how to invoke the underlying functions and show the structures. 


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Learn more about F# at http://fsharp.org
// See the 'F# Tutorial' project for more help.

open System
open System.IO
open java.util
open java.io
open edu.stanford.nlp.pipeline
open edu.stanford.nlp.ling
open Utils.NLPUtils
open Utils.NLPExtensions
open edu.stanford.nlp.util
open edu.stanford.nlp.trees
open edu.stanford.nlp.semgraph
open Utils.NLPStructures
open edu.stanford.nlp.coref

[<EntryPoint>]
let main argv = 
    let text = "Kosgi Santosh sent an email to Stanford University. He didn't get a reply email.";

    // Annotation pipeline configuration
    let props = Properties()
    props.setProperty("annotators","tokenize, ssplit, pos, lemma, ner, parse, dcoref") |> ignore
    props.setProperty("ner.useSUTime","0") |> ignore

    let pipeline = StanfordCoreNLP(props)

    // Annotation
    let annotation = Annotation(text)
    pipeline.annotate(annotation)

    //get annotation info
    let keys = annotation.GetToken<HashMap>(typeof<CorefCoreAnnotations.CorefChainAnnotation>)
    let mentions = keys |> Seq.exactlyOne |> getMentions        

    let sentences = 
        [
            let sentences = annotation.GetToken<CoreMap>(typeof<CoreAnnotations.SentencesAnnotation>)

            for s in sentences do
                let tokens = s.GetToken<CoreLabel>(typeof<CoreAnnotations.TokensAnnotation>)
                let words = getWords tokens

                let t = s.GetToken<Tree>(typeof<TreeCoreAnnotations.TreeAnnotation>)  
                let tree = t |> Seq.exactlyOne |> buildTree words
       
                let deps = s.GetToken<SemanticGraph>(typeof<SemanticGraphCoreAnnotations.CollapsedDependenciesAnnotation>)
                let relationships = deps |> Seq.exactlyOne |> getDependencyGraph words
                let sentence = { Words = words; Dependency = relationships; Tree = tree; }
                yield sentence
            ]

    let story = 
        {
            CrossLinks = mentions;
            Sentences = sentences;
        }

    printfn "%O" story

    0 // return an integer exit code


The second file is the library file. I do not think the structure will stay same after two weeks. I might decide to add more fields. But currently the foundation is there.



1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
namespace Utils

module NLPStructures = 

    type Word = string
    type Ner = string
    type POS = string
    type Index = int
    type Relationship = string
    type Span = int * int
    type Head = int * string
    type SentenceIndex = int
    
    type WordType = 
        {
          Word : Word
          Ner: Ner
          POS: POS
          Index: Index
        }

        member this.IsSame word = 
            match this with
            | { Word = w; } -> w = word

        member this.IsSame index = 
            match this with
            | { Index = i } -> i = index

    type MentionEntity =
            {
                Index: Index
                Relationship: Relationship
                Span : Span
                Head : Head
                SentenceIndex : SentenceIndex
            }
    
    type RepresentiveMention = MentionEntity

    type CrossLinkType =
        {
            Index: Index
            RepresentiveMention : RepresentiveMention
            Mentions : MentionEntity list
        }
    
    type DependencyGraph = 
        | Link of Relationship * WordType * WordType
        | CrossLink of CrossLinkType
        
    type TreeNode = 
        | Node of string * WordType
        | SubNodes of POS * TreeNode list
    
    type SentenceType =
        {
            Words: WordType list
            Dependency: DependencyGraph list
            Tree: TreeNode
        }

    type StoryType = 
        {
            CrossLinks : CrossLinkType list
            Sentences : SentenceType list
        }

module NLPUtils =
    open edu.stanford.nlp.trees
    open edu.stanford.nlp.ling
    open edu.stanford.nlp.semgraph

    open NLPStructures

    let toEnumerable<'T> (obj:obj) = 
        let l = obj :?> java.util.ArrayList
        l |> Seq.cast<'T>    
            
    let toJavaClass (t:System.Type) = java.lang.Class.op_Implicit(t)

    let findWord (words:WordType list) (word:Word) = 
        words |> Seq.find (fun n -> n.IsSame(word))
    let findIndex (words:WordType list) (i:Index) = 
        words |> Seq.find (fun n -> n.IsSame(i))

    let inline getObjFromMap (x:^T) t = 
        let key = t |> toJavaClass
        (^T : (member get : java.lang.Class -> obj) (x, key) )

    let getWords (tokens:seq<CoreLabel>) = 
        [ 
            for token in tokens do
                let word = typeof<CoreAnnotations.TextAnnotation> |> getObjFromMap token :?> Word
                let pos  = typeof<CoreAnnotations.PartOfSpeechAnnotation> |> getObjFromMap token :?> POS
                let ner  = typeof<CoreAnnotations.NamedEntityTagAnnotation> |> getObjFromMap token :?> Ner
                let index = token.index()
                let word = { Word = word; Ner = ner; POS = pos; Index = index }
                yield word
        ]

    let getDependencyGraph words (deps:SemanticGraph)  = 
        [
            for edge in deps.edgeListSorted().toArray() |> Seq.cast<SemanticGraphEdge> do
                let gov = edge.getGovernor()
                let dep = edge.getDependent()

                let govEntity = findIndex words (gov.index())
                let depEntity = findIndex words (dep.index())

                let e = Link(edge.getRelation().getLongName(), govEntity, depEntity)
                yield e
        ]
    
    let rec buildTree words (tree:Tree)  = 
        let label = tree.value()
        let children = tree.children()
        if children.Length = 0 then
            let x = tree.label() :?> CoreLabel
            let i = x.index()

            let entity = findIndex words i
            Node(label, entity)
        else
            let nodes = children |> Seq.map (fun tree -> buildTree words tree) |> Seq.toList
            SubNodes(label, nodes)

    let getMention (mention:edu.stanford.nlp.coref.data.CorefChain.CorefMention) = 
        let mentionId = mention.mentionID
        let span = (mention.startIndex, mention.endIndex)
        let relation = mention.animacy.name()
        let head = (mention.headIndex, mention.mentionSpan)
        let sentenceIndex = mention.sentNum
        let m = { Index = mentionId; Relationship = relation; Span = span; Head = head; SentenceIndex = sentenceIndex; }
        m

    let getMentions (keys:java.util.HashMap) = 
        [
            for key in keys.keySet().toArray() do
                let v = keys.get(key) :?> edu.stanford.nlp.coref.data.CorefChain
                let representiveMention = v.getRepresentativeMention()
                let m = getMention(representiveMention)

                let index = v.getChainID()
                let mentions = v.getMentionsInTextualOrder().toArray()
                let ms = mentions 
                         |> Seq.cast<edu.stanford.nlp.coref.data.CorefChain.CorefMention> 
                         |> Seq.map getMention
                         |> Seq.toList
                let r = { Index = index; RepresentiveMention = m; Mentions = ms; }
                yield r
        ]
    
    let returnSeq<'T> (x:obj) = 
        if x :? java.util.ArrayList then
            toEnumerable<'T> x
        else
            Seq.singleton (x :?> 'T)
    
module NLPExtensions = 
    open NLPUtils
    open edu.stanford.nlp.util

    type CoreMap with
        member this.GetToken<'T> (t:System.Type) = 
            t |> getObjFromMap this |> returnSeq<'T> 

The execution result shows below:




Saturday, November 3, 2018

SelfNote: Stanford NLP

I create this page as the master page for using F# on Stanford NLP.

Monday, October 29, 2018

F# Stanford NLP is running

After some configuration, I can successfully run the first NLP project with F#. Special thanks to Sergey's post! The post is very informative. His solution is based on the F# interactive while I prefer to use the project-based solution.

Sergey points out that one of the common problems to setup is the path problem. His claim is so true. I had stuck in this problem for days. Here is the process I followed.


  • Open Visual Studio 2017 and create an F# console application. 
    • I tried .net core app; it does not work as the IKVM has the dependency on the .NET framework
  • compile the F# console application and remember the debug folder location
  • Open NuGet and retrieve Stanford NLP CoreNLP. The current version is 3.9.1
    • Current Stanford NLP is 3.9.2. I suggest you download 3.9.1 version
  • download the Standard NLP 3.9.1 zip file
  • unzip the 3.9.1 file to the F# console app debug folder
  • go the unzipped folder and find the model JAR file

  • download WINRAR to unzip the JAR file to a folder, this folder should contain a folder called "EDU"
  • copy the "EDU" folder up to debug folder, so the structure in the "DEBUG" folder is like the following.
  

The F# file I was using is listed below. Set the "EDU" folder to the debug folder can save you from setting the CurrentDirectory. 


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Learn more about F# at http://fsharp.org
// See the 'F# Tutorial' project for more help.

open System
open System.IO
open java.util
open java.io
open edu.stanford.nlp.pipeline

[<EntryPoint>]
let main argv = 
    let text = "Kosgi Santosh sent an email to Stanford University. He didn't get a reply.";

    // Annotation pipeline configuration
    let props = Properties()
    props.setProperty("annotators","tokenize, ssplit, pos, lemma, ner, parse, dcoref") |> ignore
    props.setProperty("ner.useSUTime","0") |> ignore

    let pipeline = StanfordCoreNLP(props)

    // Annotation
    let annotation = Annotation(text)
    pipeline.annotate(annotation)

    // Result - Pretty Print
    let stream = new ByteArrayOutputStream()
    pipeline.prettyPrint(annotation, new PrintWriter(stream))
    printfn "%O" <| stream.toString()
    stream.close()

    printfn "%A" argv
    0 // return an integer exit code

Executing the NLP program seems taking a lot of memory. My program uses 2G memory and takes a while to show the result. Hopefully, your computer is faster enough. :)

Thursday, October 25, 2018

F# Enum usage II

I want to take a quick note on the F# enum usage again. The supporting of the space and unique character in F# language and editor is a great feature can make your development work much more comfortable. I am in the Web API front these days.

One of the requirement is to provide options to end users. If an application only takes "excellent choice", "good option", "ok choice", and "bad and never go there" as options, I'd like to offload these values check to the type system instead of handling the error in my code.

If I can declare the enum like the following

type enum MyEnum =
    ``excellent choice`` = 0
    | ``good option`` = 1
    ....

After declaring the enum-as-string attribute on the attribute [JsonConverter(typeof(StringEnumConverter))], the output and input validation is solved in one shoot.

Monday, September 24, 2018

F# Enum's Usage

I have a web service project and I found my team constantly needs to convert enum to a string. The only conversion is adding space. It wastes lots of time and involves in reflection which slows down the run time performance.

Enum type is one of the favorite types in F#. C#'s enum type does not have the ability to define a value with space. Having an enum value with space is very important because this feature can save me lots of time to output enum value as string.

For example, if the enum value can be "Post Release", the ToString function can output a nice string and won't have to use attribute and reflection to do the job. C# does have the ability to have space in enum but it will need to use reflect and emit to generate the type. If you can use F#, the problem can be easily solved. Please check the following F# code:

namespace ClassLibrary1

type public EnumEng =
    Registration = 0
    | ``Under Review``=1
    | Approval = 2
    | Release = 3
    | ``Post Release`` = 4

type public EnumChn =
    注册 = 0
    | 审批 = 1
    | 批准 = 2
    | 发布 = 3
    | 发布后 = 4

type public EnumIndex =
    Reg = 0
    | Review = 1
    | Approval = 2
    | Release = 3
    | PostRelase = 4


module Test =
    let a = EnumEng.``Under Review``
    let b = EnumChn.审批

In the C# side, the intellisense won't display the enum value if it contains space. However, it will be displayed in debug mode. You can execute the following code and stop at the end of the function.

        static void Main(string[] args)
        {
            //get all string from enum0
            var strs = Enumerable.Range(0, 5)
                                 .Select(n => (ClassLibrary1.EnumEng)n)
                                 .Select(n => n.ToString())
                                 .ToList();

            // get all string from enum2
            var i = Enumerable.Range(0, 5)
                              .Select(n => (ClassLibrary1.EnumChn)n)
                              .Select(n => n.ToString())
                              .ToList();

            // parse string to enum
            var v = strs.Select(n => Enum.Parse(n))
                        .ToList();

            var x = ClassLibrary1.EnumIndex.PostRelase;

            var str = (ClassLibrary1.EnumChn)x;
        }

Both # and C# support non-English variable name, it will provide a way to localize the output as well. From the sample above, the EnumIndex is the type can used in C#/F# code. Once the value needs to be output as string, it can be convert to EnumEnglish (English string) or EnumChinese(Chinese string).



Is that convenient?

Thursday, February 13, 2014

Reverse List Every K Node

Today I found an question and decide to use F# pattern match to give it a try.

The question is reverse a list every k node. For example, if the input list is [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] and k = 3, the output will be [3; 2; 1; 6; 5; 4; 9; 8; 7; 10].

When I use pattern matching, I always like recursive implementation.

 let arr = [1..10]  
 let rec reverse arr i =   
   let reverse2 arr =   
     arr |> List.rev  
   let rec getHeadTail arr i =   
     match i with  
     | 0 -> ([], arr)  
     | _ ->   
       match arr with   
       | [] -> ([], [])  
       | h::t ->   
         let (head,tail) = getHeadTail t (i-1)  
         ([h]@head, tail)  
   let headArr, tail = getHeadTail arr i  
   match tail with  
   | [] -> reverse2 headArr  
   | _ -> reverse2 headArr @ reverse tail i  
 reverse arr 6  

Wednesday, February 12, 2014

F# Code Snippet Updated

I updated the F# code snippet addon for Visual Studio 2013. I will upload the source code to  once the source code is located. I really need to clean up the source code folder. There is no recompile is needed. The root cause for previous addon does not work on VS2013 is because this. The fix is simple, 


  1. download the code snippet vsix file
  2. rename it to .zip file because it is a zip file
  3. find the vsixmanifest file
  4. change InstallationTarget to


Sunday, November 17, 2013

Why F# Type Provider?

F# type provider is a very nice feature. I was asked several times why I need type provider? Just because of the intellisense? I believe there should be something else. In the current team, I found people "hate" type, they prefer to use C# object all the times. Now I realize why type is so important and why type can increase code quality.

I want to use a simple approval process as a sample. For my understanding, a type defines the meaning of a area of memory and certain operations which can be executed on this type.

The sample is simple. You can have something to be approved by lead, manager, and director. If a lead approves, it returns a manager type. If manager disapproves, the process will stop and director won't know it. After director's approval, this process stops. The type provider can have three types, director's approve method returns nothing while other type's approve method return higher level type. Lead's approve method returns manager, and manager's approve method returns director.

I'd bet people can say I can use a single type to do the same job. A general class can be used to create three instances. The director instance's approve method can return NULL or any special value to stop the approval process. It can solve this problem provides you know director's approval will stop this process beforehand. A runtime error is not far away if this information is not known beforehand. The type provider uses type to provide the information. After you invoke director's approve method, which returns NULL, user will know immediately that this process is terminated.

I would say in this case, type is a way to move runtime check/error to compile time. The attached is the demo project for this approval process.

Friday, November 8, 2013

Use F# to Write PowerShell Snapin & Cmdlet

When I was in Minneapolis, I was thinking to use the F# to write PowerShell snapin and cmdlet. I got the feeling that this can speed our development speed.

Because I use Visual Studio 2012 and it generates the .NET 4 binary. So I need to install PowerShell 3.0 in order to use .NET 4.0. You can use $psversiontable to check the CLR runtime version, make sure it is a number equal or greater than 4.

 namespace Log4NetPsSnapIn  
 open System  
 open System.Management.Automation  
 open System.ComponentModel  
 [<RunInstaller(true)>]  
 type Log4NetSnapIn() =  
   inherit PSSnapIn()  
   override this.Name with get() = "aa"  
   override this.Vendor with get() = "bb"  
   override this.Description with get() = "dd"  
 [<Cmdlet(VerbsCommunications.Write, "Hi")>]  
 type WriteHelp() =   
   inherit Cmdlet()  
   override this.ProcessRecord() =   
     base.WriteObject("help");  

After compiling the above code, a DLL is generated. You have to use installutil.exe to add the snapin. The PowerShell snapin has Name = "aa", so you can use Add-PsSnapIn aa to load the DLL. You can also use installutil.exe /u to uninstall the snapin from your system. Make sure you open the cmd window or powershell window with administrator privilege.

  • If you are running 64-bit version machine, make sure you use installUtil.exe under C:\Windows\Microsoft.net\Framework64\. 
  • if your OS is 32-bit, you can use installUtil.exe under C:\Windows\Microsoft.net\Framework\


I like the way F# write PowerShell snapin. The code is concise and easier to understand.

Monday, September 30, 2013

Web Service using F#

this is a code to read file from local disk:

make sure it runs in the console application.

 open System  
 open System.IO   
 open System.ServiceModel  
 open System.ServiceModel.Web  
 let siteRoot = @"c:\myCode\"  
 [<ServiceContract>]  
 type MyContract() =  
   [<OperationContract>]  
   [<WebGet(UriTemplate="{file}")>]  
   member this.Get(file:string) : Stream =  
     printfn "Requested : '%s'" file  
     let path = Path.Combine(siteRoot, file)  
     let fileExists = File.Exists(path)  
     if fileExists then  
       WebOperationContext.Current.OutgoingResponse.ContentType <- "text/html"  
       let bytes = File.ReadAllBytes(path)  
       upcast new MemoryStream(bytes)  
     else  
       printfn "cannot find %s" path  
       upcast new MemoryStream()  
 let startAt address =  
   let host = new WebServiceHost(typeof<MyContract>, new Uri(address))  
   host.AddServiceEndpoint(typeof<MyContract>, new WebHttpBinding(), "")  
    |> ignore  
   host.Open()  
   host  
 let server = startAt "http://localhost:8081/"  
 printfn "started service..."  
 ignore <| System.Console.Read()  
 printfn "closing service..."  
 server.Close()  
 printfn "closed"  

Saturday, January 26, 2013

Generated Type Provider and Code Generation

Let me finish the generated type provider and 100% move to Hadoop and big data area. In previous postings (1 and 2), I explained how to write generated type provider. The following are some pain points you might encountered when write your own generated type provider.

I currently use generated type provider to generate DLL. This is my main task. Currently, there is not so many document about generated type provider available, especially how to use F# expression to generate the binary. C# provides TypeBuilder to create types in a dynamic DLL, I use F# type provider to generate DLL.

  • Define a field and property.
let providedField = ProvidedField("field", typeof<System.Func<string, string, string, obj, obj>>)  
let providedProperty = ProvidedProperty("Property", typeof<System.Func<string, string, string, obj, obj>>,   
                   GetterCode = (fun [this] -> Expr.FieldGet (this, providedField)),  
                   SetterCode = (fun [this;v] -> Expr.FieldSet(this, providedField, v)))  
  • ProvidedField is a FieldInfo, ProvidedMethod is a MethodInfo, so everywhere you can to pass in standard .NET type, you can use Provided types.
  • Constructor code needs to be modified to generate the your code. This piece needs to be added to the .fs. For generated code type provider, you do not have to return < @@ baseClass() @@ > in your constructor code.  
         let expr = pcinfo.GetInvokeCodeInternal true parameters  
         let locals = Dictionary<Quotations.Var,LocalBuilder>()  
         let expectedState = ExpectedStackState.Empty  
         emitExpr (ilg, locals, parameterVars) expectedState expr  


  • NewDelegate has not been implemented yet. The bypass is to create a module with your function and pass in the function as expression.
  • Specify the generated DLL path, where cfg is TypeProviderConfig. You can use any reflector tool to check the generated DLL.
 let providedAssembly = new ProvidedAssembly(System.IO.Path.Combine(cfg.ResolutionFolder, "GeneratedBinary.dll"))  


  • Get C# lambda from F# function. 
Very simple, you can just do System.Fun(fun i -> i+1). 


Monday, January 14, 2013

Generated Type Provider Sample Published on Codeplex

Steffen asked me to provide a generated type provider sample to help understand the type provider API change and generated type provider itself. Changeset 19125 is made minutes ago to FSharp 3.0 Sample pack. The sample shows how to write a generated type provider.

In the solution, there are three projects:

  1. GeneratedTypeProvider project is the one generating the type provider using the new API. The generated type provides only one function which return a constant value 1.
  2. ConsoleApplication2, which is F# project, references to GeneratedTypeProvider project to expose the generated type from type provider
  3. ConsoleApplication1 references to ConsoleApplication2 project to reference type from C# code.
The way I use generated type provider is to generated DLL. I will start several post to help interested user to explore this area more after my sinus infection is getting better.


Friday, January 11, 2013

Generated Type Provider API Changes

Erased type provider is not a new idea for many F# users, but the problem I am facing is to generate a really DLL which can be consumed by C# project. I use type provider as a code generation tool. If you are thinking about the same thing. Here is how to make your erased type provider to be a generated type provider. The MSDN document does not reflect the recent change in the type provider API's.


  • you need to declare the ProvidedAssembly.

let providedAssembly = new ProvidedAssembly(System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), ".dll"))


  • For the generated type, for example the regexTy, invoke the following statements (you have to remove the space between < and -)
    do 
        regexTy.IsErased < - false
        regexTy.SuppressRelocation < - false
        providedAssembly.AddTypes([regexTy])

Hopefully this can save you 10 minutes.. :-)

Saturday, December 22, 2012

Functional Programming and/or F# Conferences


There are some conferences I've noticed for year 2013. I will update this page regularly.



Saturday, December 15, 2012

Debug F# Type Provider

Recently I am trying to use Type Provider (TP) in our production code. The first question I got is how to debug TP. The following is a way to debug it.

  • download the type provider template or create your own project using the type provider API from codeplex.
  • create a F# console Application in the solution
  • from the F# console application add reference to the type provider project. Let us call this project ConsoleApplication2
  • go to type provider project
  • right click the project and open the project property
  • find the "Debug" tab in the project property
  • set the property like the image shown below:



  •  Set the type provider project as start up project.
When the type provider project starts, it starts visual studio to open the Console application. You can put your break point in the type provider code. Once the debug is finished, the Visual Studio is closed and you are free to modify your code and rebuild the type provider code.

This approach does not requires to close and reopen the Visual Studio.

Sunday, December 9, 2012

Remove F# snippet shortcut

I got email from Jack two weeks ago. He said F# code snippet is "too active". Yes, when you type, some shortcut keys will pop up and this is very annoying. The quick (and probably dirty) fix is to remove the shortcut key in the snippet file. The script file to remove the shortcut key is listed below. You can run it targeting to the snippet folder. Usually the folder is My Document \ < Visual Studio Folder > \Code Snippets\Visual F#.

If you are curious where is is the Shortcut key in the snippet file. Here is the screenshot.



The latest version snippets on the codeplex project does not have any shortcut key. You can download these snippets from codeplex project as well.

Although the shortcut key is removed, you still use Ctrl+K,X to show the snippet dialog.

 let (|ValidFolder|_|) folder =   
   match folder with  
   | _ when (File.GetAttributes(folder) &&& FileAttributes.Directory = FileAttributes.Directory) -> Some ValidFolder  
   | _ -> None  

 let removeShortcutTag (xmlFile:string) =   
   let doc = XDocument.Load xmlFile  
   doc.Descendants()  
   |> Seq.tryFind (fun decendent -> decendent.Name.LocalName = "Shortcut")  
   |> function  
     | Some node ->   
       File.SetAttributes (xmlFile, ~~~FileAttributes.ReadOnly  
                      &&& ~~~FileAttributes.Hidden  
                      &&& ~~~FileAttributes.System)  
       node.Value <- String.Empty  
       doc.Save(xmlFile)  
     | None -> ()  

 let processXMLFiles folder =   
   let xmlFiles = Directory.GetFiles(folder, "*.snippet")  
   xmlFiles  
   |> Seq.iter (fun xmlFile -> removeShortcutTag xmlFile)  

 let rec processXML folder =   
   match folder with  
   | ValidFolder ->   
     let subFolders = Directory.EnumerateDirectories(folder)  
     processXMLFiles folder  
     subFolders  
     |> Seq.iter processXML  
   | _ -> ()  

 processXML @"C:\MyCode\fsharpcodesnippet"  

Thursday, December 6, 2012

F# Contract Position


Please contact recruiter directly. 


  • ·         .Net (3.5 or 4.0) F# or C# programming expertise required
  • In depth understanding of object-oriented analysis and design with a broad understanding of software design patterns preferred
  • Understanding of IT in Financial Services background & domain knowledge –equity, fixed income, credit and derivatives products preferred
  • ·         Experience in working in a fast paced, front-middle office or Risk/Margin preferred
  • Experience in working with Middleware components such as Solace, Tibco RV, EMS preferred. XML, data binding and SOAP web services a plus
Self starter, passionate and enthusiastic attitude.

This is an Immediate need.

ONLY US CITIZENS PLEASE....
 
Srikanth Mandapati
HuMetis Technologies Inc
2 King Arthur Court
Lakeside W A-1
North Brunswick, NJ 08902
Phone: (609) 910-3391
Fax: (877) 451-5544