F# Actor: An Actor Library

Wikipedia, defines an actor as -

An actor is a computational entity that, in response to a message it receives, can concurrently:

  • send a finite number of messages to other actors;
  • create a finite number of new actors;
  • designate the behavior to be used for the next message it receives.

Recently there has been some discussion in the F# open source community about an Akka like actor framework for F#. The following post introduces a very early version of the framework, in the hope that it will get some community interest and contributions.

Creating actors and sending messages

To create an actor we need to simply provide a name and a function that takes an actor instance and returns a unit Async computation

let multiplication = 
    (fun (actor:Actor<_>)  ->
        async {
            let! (a,b) = actor.Receive()
            let result = a * b
            do printfn "%A: %d * %d = %d" actor.Path a b result
        }
    )

let addition = 
    (fun (actor:Actor<_>) ->
        async {
            let! (a,b) = actor.Receive()
            let result = a + b
            do printfn "%A: %d + %d = %d" actor.Path a b result
        }
    )

let calculator = 
    [
       Actor.spawn (ActorPath.create "calculator/addition") addition
       Actor.spawn (ActorPath.create "calculator/multiplication") multiplication
    ]

Here we have created two actors, one that carries out multiplication and one that carries out addition. To send a message to the actors we can simply get the instance and call the post method.

calculator.[0].Post((5,2))

However in an actor framework having to directly reference the actors to call post on them can be some what limiting. So when each actor is created it is assigned a path. The path is created with the following schema (actor://{machinename}/{path}). We can use this path to resolve the actor,

"actor://main-pc/calculator/addition" ?<-- (5,2)

If we know that this actor is local then we do not need to qualify the path.

"calculator/addition" ?<-- (5,2)

In addition to resolving single actors we can also broad cast to several actors at once by providing a partial path,

"calculator/" ?<-- (5,2)

Sending Messages to Remote Actors

Messages are sent via transports. Out of the box, the framework provides a TCP transport based on the high performance Fracture I/O library. Before you can send remote messages you must register a transport.

let transport = new FractureTransport({ Port = Some 8080}) :> ITransport
Remoting.registerTransport Serialisers.Binary transport

When a transport is created it is wrapped in a actor of Actor and path ‘transports/{scheme}’ in the case of the fracture transport this would be ‘transports/actor.fracture’. This actor is then supervised (see below) by the system/remotingsupervisor actor, which is initialised the a OneForOne strategy so will restart the transport if it errors at any point. Once a transport is registered we can then send a message to a remote actor by using a fully qualified actor path, for example,

"actor.fracture://10.256.76.94:8080/calculator/addition" ?<-- (5,2)

notice here that the scheme selects which transport the message will be sent on. If you wanted to send a message on another registered transport (http for example), the path would be,

"actor.http://10.256.76.94:8082/calculator/addition" ?<-- (5,2)

Supervisors

Supervisors, provide a way to monitor make decisions about what to do when a actor errors. How the supervisor responds when an actor receives an error depends on the strategy provided (for more info see here.

To create a supervised actor, we can simply do the follwoing

let err = 
    (fun (actor:Actor<string>) ->
        async {
            let! msg = actor.Receive()
            if msg <> "fail"
            then printfn "%s" msg
            else failwithf "ERRRROROROR"
        }
    ) |> Actor.spawn (ActorPath.create "err_0")

let supervisor =  Actor.supervisor (ActorPath.create "oneforone") Supervisor.OneForOne [err]

if we now post ‘fail’ to this actor it will throw an exception and the supervisor will step in and restart the actor.

Conclusion

This has just been a brief introduction into the framework, there is much more in the pipeline the project is in its very early stages. I welcome anyone who wants to contribute and shape this into a fully fledged actor framework. So basically rip it apart tell let me know what you like don’t like, send pull requests raise bugs, feature requests, improve documentation. Any contribution will be welcomed.

The source for this can be found on GitHub here. And more complete documentation here

Posted in Development | Tagged , | Leave a comment

F# 3 and Raven DB

Ok so I have blogged about these to before. Previously, F# didn’t have brilliant support for Linq. F# Expressions couldn’t `easily` be converted to the Linq expression trees that the RavenDB API required. This caused somewhat of a mis-match between the two which made Raven difficult but not impossible to use from F#. My previous blog introduced a library which is available for Raven clients prior to version 2.0, to bridge this gap, and tried to make Raven more natural to use from F#. However as of Raven 2.0 this library has been removed. The reasons are explained here. I don’t disagree with the reasons ayende cut the support
I wouldn’t want to support something I had little knowledge of either. However things have changed…. :)

The advent F# 3 and query expressions

So we are now in the era of F# 3.0 and things have changed somewhat. F# is now truly in the data era… Information Rich programming is an awesome feature of F# manifested in the
form of `Type Providers` and `Query Expressions`. If you haven’t read about or don’t know what type providers are then I encourage you to check them out here. Type providers are not really applicable for use with RavenDB see it is schemaless so for the rest of thispost we will focus on `Query Expressions`. It is this feature that means the gap between Linq and F# no longer exists. If you are familiar with

var result = (from x in xs do
	      where x.Published >= someDate
	      select x.Name).ToArray()

then the query expression syntax shouldn’t feel that different,

let result =
     query {
            for x in xs do
	        where (x.Published >= someDate)
	        select x.Name
	   } |> Seq.toArray

So What about RavenDB???

Using RavenDB from C# is well documented and things are not that different when using it from F#. The in’s and out’s are well known and lets face it the API is your safety net. It doesn’t let you kill yourself, in fact you have to try very hard to actually do anything really bad in RavenDB. This is I think the best feature of RavenDB.

So, what are the things that we need to be aware of when using RavenDB from F#? First things first, initializing the document store. This can be done pretty much the same as in C#

let store = new DocumentStore(Url = "http://localhost:8080")

and this is all well and good if we just use straight forward POCO objects. But what if we want to use F# record or Union types? We need to make a few simple changes.
Lets first consider F# record types, all we need to do here is declare the `Id` property as mutable.

type BlogPost = {
	mutable Id : string
	Body : string
	....//other members
}

Simple eh?, but what about Union types, Maps, F# lists? These are a little more complex as Json.NET doesn’t do the correct thing to serialize these out of the box. However Json.NET and the
internalised Raven counterpart does have an extension point and a UnionTypeConverter or MapTypeConverter as Json.NET implementations can be found here. To use this we need to modify our
document store setup a little to include the converter.

let store =
        let customiseSerialiser (s : JsonSerializer) =
            s.Converters.Add(new MapTypeConverter())
            s.Converters.Add(new UnionTypeConverter())

        let store = new DocumentStore(Url="http://localhost:8080")
        store.Conventions.CustomizeJsonSerializer <- (fun s -> (customiseSerialiser s))
        store.Initialize()

Querying raven

With the document store setup we can now start querying Raven. As with any Raven query we need to create a session from our document store, then we need to create the query.

let getPostsAsOf store asOfDate = 
    use session = store.OpenSession()
    query {
	for post in session.Query() do
	where (post.Published >= asOfDate)
	select post
    }

The above creates a query that is pending execution. To execute this we can run,

let posts = 
    getPostsAsOf store (DateTime.Now.AddDays(-2.).Date) 
    |> Seq.toArray

this will give us an array of BlogPosts published from 2 days ago. Notice we had to enumerate to an array for the query to actually be executed. This is the same execution semantics
as C#; and it is important to realise that there isn’t really any magic going on in the world of F#, it is still just a .NET lanuguage it still compiles to CIL and is fully
interoperable with any other .NET library.

Indexes

OK so things haven’t got much better here in terms of static indexes. Basically you still need to define them in C# and then you can extend the document initialization process by
including the assembly that contains the index definitions. However in Raven 2.0, dynamic indexes and promotion to permanent indexes have been massively improved, which reduces the need to create static indexes.

Posted in Development | Tagged , | Leave a comment

Option Operators

We often have to represent the absence of data within a collection of values. In C# the default type to-go to is an Nullable, F# 3.0 introduced the Microsoft.FSharp.Linq.NullableOperators module to help with comparisons and arithmetic over this type.

The Nullable type can still be somewhat tiresome to use in F# though as it can lead to adding lots of type constraints for example

type NullableSeq<'a when 'a : (new : unit ->'a) 
                    and 'a : struct 
                    and 'a :> ValueType> = seq<Nullable<'a>>

I think a nicer approach is to replace Nullable with Option, to relax some of these type constraints.

type OptionSeq<'a> = seq<Option<'a>>

however in doing this we have lost the nice operators. But this is fairly easy to recreate as the semantics of Nullable and Option are approximately the same. So with a quick copy of the NullableOperators module and some simple find and replace we have the exact same set of operators.

module OptionOperators

    open System
    let (?>=) (x : Option<'T>) (y: 'T) = x.IsSome && x.Value >= y

    let (?>) (x : Option<'T>) (y: 'T) = x.IsSome && x.Value > y

    let (?<=) (x : Option<'T>) (y: 'T) = x.IsSome && x.Value <= y

    let (?<) (x : Option<'T>) (y: 'T) = x.IsSome && x.Value < y

    let (?=) (x : Option<'T>) (y: 'T) = x.IsSome && x.Value = y

    let (?<>) (x : Option<'T>) (y: 'T) = not (x ?= y)

    let (>=?) (x : 'T) (y: Option<'T>) = y.IsSome && x >= y.Value

    let (>?) (x : 'T) (y: Option<'T>) = y.IsSome && x > y.Value

    let (<=?) (x : 'T) (y: Option<'T>) = y.IsSome && x <= y.Value

    let (<!--?) (x : 'T) (y: Option<'T-->) = y.IsSome && x < y.Value

    let (=?) (x : 'T) (y: Option<'T>) = y.IsSome && x = y.Value

    let (<>?) (x : 'T) (y: Option<'T>) = not (x =? y)

    let (?>=?) (x : Option<'T>) (y: Option<'T>) = (x.IsSome && y.IsSome && x.Value >= y.Value)

    let (?>?) (x : Option<'T>) (y: Option<'T>) = (x.IsSome && y.IsSome && x.Value > y.Value)

    let (?<=?) (x : Option<'T>) (y: Option<'T>) = (x.IsSome && y.IsSome && x.Value <= y.Value)

    let (?<!--?) (x : Option<'T-->) (y: Option<'T>) = (x.IsSome && y.IsSome && x.Value < y.Value)

    let (?=?) (x : Option<'T>) (y: Option<'T>) = (not x.IsSome && not y.IsSome) || (x.IsSome && y.IsSome && x.Value = y.Value)

    let (?<>?) (x : Option<'T>) (y: Option<'T>) = not (x ?=? y)

    let inline (?+) (x : Option<_>) y = if x.IsSome then Some(x.Value + y) else None
    let inline (+?) x (y: Option<_>) = if y.IsSome then Some(x + y.Value) else None
    let inline (?+?) (x : Option<_>) (y: Option<_>) = if x.IsSome && y.IsSome then Some(x.Value + y.Value) else None

    let inline (?-) (x : Option<_>) y = if x.IsSome then Some(x.Value - y) else None
    let inline (-?) x (y: Option<_>) = if y.IsSome then Some(x - y.Value) else None
    let inline (?-?) (x : Option<_>) (y: Option<_>) = if x.IsSome && y.IsSome then Some(x.Value - y.Value) else None

    let inline ( ?*  ) (x : Option<_>) y = if x.IsSome then Some(x.Value * y) else None
    let inline ( *?  ) x (y: Option<_>) = if y.IsSome then Some(x * y.Value) else None
    let inline ( ?*? ) (x : Option<_>) (y: Option<_>) = if x.IsSome && y.IsSome then Some(x.Value * y.Value) else None

    let inline ( ?%  ) (x : Option<_>) y = if x.IsSome then Some(x.Value % y) else None
    let inline ( %?  ) x (y: Option<_>) = if y.IsSome then Some(x % y.Value) else None
    let inline ( ?%? ) (x : Option<_>) (y: Option<_>) = if x.IsSome && y.IsSome then Some(x.Value % y.Value) else None

    let inline ( ?/  ) (x : Option<_>) y = if x.IsSome then Some(x.Value / y) else None
    let inline ( /?  ) x (y: Option<_>) = if y.IsSome then Some(x / y.Value) else None
    let inline ( ?/? ) (x : Option<_>) (y: Option<_>) = if x.IsSome && y.IsSome then Some(x.Value / y.Value) else None
Posted in Development, Uncategorized | Tagged , | 2 Comments

F# IKVM Type Provider

After reading Sergey Tihon’s post about IKVM and the stanford parser. I thought I’d try and create a IKVM type provider.

The first version can be found on my GitHub account here.
The following code shows a simple sample on how to use the type provider.

    let\[<Literal>\] jar = @"D:\Appdev\IKVM.TypeProvider\IKVM.TypeProvider.Tests\SimpleJar\out\artifacts\SimpleJar.jar"
    let\[<Literal>\] ikvmPath = @"D:\Appdev\IKVM.TypeProvider\IKVM\bin\"

    type Jar = IKVM.IKVMProvider<JarFile=jar, IKVMPath=ikvmPath>
    type HW = Jar.hello.HelloWorld

    \[<EntryPoint>\] 
    let main(args) =
        let hw = new HW("IKVM")
        printf "%s" (hw.Say("Hello from java, well .NET"))
        printf "%s" (hw.Close())
        System.Console.ReadLine() |> ignore
        0

The above is the same sample included in the source. As you can see it requires an IKVM distribution your machine and requires your consuming project to reference IKVM.OpenJDK.Core.

This is very early days, for this so I would be surprised if it works for anything even moderately complex. But I hope to change this to support everything that IKVM supports assuming I get the time, in my day job :) . Feel free to have a play and let me know what works and what doesn’t.

The biggest gripe I have at the minute is that the type providers don’t allow direct references to generated types, hence HW representing the class I wish to use. I would prefer to just open the “namespace“ as a type and then use the classes from there. Like the following

    let\[<Literal>\] jar = @"D:\Appdev\IKVM.TypeProvider\IKVM.TypeProvider.Tests\SimpleJar\out\artifacts\SimpleJar.jar"
    let\[<Literal>\] ikvmPath = @"D:\Appdev\IKVM.TypeProvider\IKVM\bin\"

    type Jar = IKVM.IKVMProvider<JarFile=jar, IKVMPath=ikvmPath>
    type helloNS = Jar.hello

    \[<EntryPoint>\] 
    let main(args) =
        let hw = new helloNS.HelloWorld("IKVM")
        printf "%s" (hw.Say("Hello from java, well .NET"))
        printf "%s" (hw.Close())
        System.Console.ReadLine() |> ignore
        0

I suspect not being able to do this will become problematic for large assemblies. as you will have to create an indirect reference for each type that you used.

Posted in Uncategorized | Tagged , , | 2 Comments

F# end to end

Introduction

Recently my colleague @simontcousins published an article comparing to similar projects one written in C# one written in F#. The conclusion is that for the two projects the F# one is about 4% of the size.  You can read more about this here.

Now normally, a typical project comprises of several languages / technologies.

  • Application Code -> C#
  • Build -> MSBuild/Nant
  • Deploy -> Powershell script/Batch script
  • UI (Web) -> HTML/Javascript
  • Documentation -> Word/HTML

However the F# project in question here has a profile more like this,

  • Application Code -> F#
  • Build -> F#
  • Deploy -> F#
  • UI (Web) -> HTML/CSS/Javascript
  • Documentation -> F#

Note the stack is ‘almost’ completely F# (we actually could have made this completely F# see below). Maybe I’m biased but I think that this is a huge benefit for maintainability I only need to have my F# brain switched on and I can change any part of the application. Sure I have to learn a few libraries, but the playfulness offered by the REPL here makes testing and experimenting easy; this is especially true when it comes writing build and deployment scripts, which I normally find quiet difficult to test.

Full stack F#

So is it possible to use F# for everything Build, Deployment, UI (Web/WPF), Documentation. The answer is simply YES!! There is just a few libraries we need to know about to achieve this. Lets look at each area of a typical application and see which libraries we can use.

Application Logic

Ok this might seem like an obvious one, just write F#, but I thought I’d use this as an opportunity to highlight some libraries that I find useful

  • FSharpx – Contains lots of extensions to the F# core modules, many useful data structures, commonly used monads, validation, type providers, async extensions etc.
  • FSharp.Data – Contains implementation of various type providers such as CSV, XML and JSON and I’m sure as the library matures we will see a lot more implementations to connect to wide variety of data sources.
  • FSharpEnt- Contains more enterprise based helpers for F#. This will soon be replaced by a newer version which reduces the overlap with FSharpx, the (very early) version can be found here, I just need to find some time to do this :) .

Build and Deployment

To build and deploy application with F# we can use FAKE. FAKE allows you to write your build and deployment scripts in F#. A simple script might look something like this

// include Fake libs
#I @&quot;..\..\tools\FAKE&quot;
#r &quot;FakeLib.dll&quot;
open Fake

// *** Define Targets ***

Description &quot;Cleans the last build&quot;
Target &quot;Clean&quot; (fun () -&gt;
    trace &quot; --- Cleaning stuff --- &quot;
)

Target &quot;Build&quot; (fun () -&gt;
    trace &quot; --- Building the app --- &quot;
)

Target &quot;Deploy&quot; (fun () -&gt;
    trace &quot; --- Deploying app --- &quot;
)

// *** Define Dependencies ***
&quot;Clean&quot;
  ==&gt; &quot;Build&quot;
  ==&gt; &quot;Deploy&quot;

// *** Start Build ***
RunParameterTargetOrDefault &quot;target&quot; &quot;Deploy&quot;

The really nice thing about this is you have the full .NET framework and the full power of F# available in your scripts. Additionally FAKE also has an accompanying website, which allows you to manage your deployment agents, so you can easily deploy, upgrade or rollback applications from a central place. As of writing this is in its early stages but the latest source for this feature can be found on my fork.

UI

How you tackle writing a UI in F# obviously depends on your choice of technologies. There are others obviously but the two I’m going to consider are WPF and HTML/CSS/Javascript.

WPF

If you choose to write your UI using WPF then things are fairly straight forward, Write XAML markup and then use code behind F#. However wiring up the code behind can be a pain because of the C# code gen involved, typically you have to load the view yourself using a XAML reader, or code the view layout in F# as in these series of examples from John Laio. If however you want to keep XAML markup then FSharpx has a XAML type provider that helps things along here.

open System
open System.Windows
open System.Windows.Controls
open FSharpx

type MainWindow = XAML&lt;&quot;Window.xaml&quot;&gt;

let loadWindow() =
    let window = MainWindow()
    window.Button1.Click.Add(fun _ -&gt;
        MessageBox.Show(&quot;Hello world!&quot;)
        |&gt; ignore)
    window.Root

[&lt;STAThread&gt;]
(new Application()).Run(loadWindow())
|&gt; ignore

See Steffan Forkmanm’s post for more information about this. Lets also not forget about first class events and the asynchronous programming model in F# that makes writing responsive UI’s that much easier.

HTML/CSS/Javascript

If you go webby then things get a little more interesting, we have several options available here.

  • WebSharper – This is a very complete web framework, I have not personally played with it yet but I understand it does everything you’d want and more. Well worth checking out.
  • FunScript – A new project, but it exploits the power of type providers to offer strongly typed access to TypeScript files @thomaspetricek has a nice talk about it here. With fun script you still have to write the HTML markup, although providing a Combinator library to emit the markup wouldn’t be that difficult. (If some one knows of one I’ll add it here), but this isn’t application logic anyway. The important stuff is still written in F# and compiled to javascript later on.

Documentation

@thomaspetricek recently released FSharp.Formatting we can generate documentation from an F# script file, using a mix of markdown and F#, for an example see this link. This can then be integrated into your FAKE build script, using a build target something like this.

Target &quot;Docs&quot; (fun _ -&gt; 
    let template = Path.Combine(currentDirectory, &quot;template.html&quot;)
    let sources = Path.Combine(__SOURCE_DIRECTORY__, &quot;samples&quot;)
    let output = docsDir
    
    Literate.ProcessDirectory(sources, template, output)

    XCopy docsDir &quot;docs&quot;
)

Conclusion

Ok I might of over stated that everything can be written in F#, certainly at the moment there is a lack of libraries for emitting XAML and HTML (with the exception of WebSharper of course). But HTML and XAML are really inconsequential when it comes the to the correctness of your application they do not contain any logic which needs to be tested they simply control layout. The important thing to take from the above is the fact that all of your logic whether it is for build, deployment, UI interaction, example documentation can be written in a type safe way using the various libraries and F# feature spoken about above.

Posted in Development | Tagged , | 12 Comments

Downgrading with Nuget

Recently I had a problem where I had blindly (and stupidly) upgraded one of my packages across an entire solution. Only to find out the version was incompatible with some of my code. Instead of making the required changes to fix the problems, due to time constraints I decided to roll back to the previous version, so I broke out the nuget package manager console.

First we need to get a list of projects that have a reference to the nuget package

 $projects =Get-Project -All | Select @{ Name="ProjectName";Expression={$_.ProjectName}}, @{Name="Has";Expression={Get-Package Newtonsoft.Json -Project $_.Name}} | where { $_.Has -ne 'Newtonsoft.Json 4.5.4' }

Then uninstall the package

$projects | select { Uninstall-Package Newtonsoft.Json -ProjectName $_.ProjectName -Force }

It is worth noting this use of the force switch here. This can be quiet dangerous as it can break other packages (see NuGet Docs)

and finally install the new one.

$projects | select { Install-Package Newtonsoft.Json -Version 4.0.8 -ProjectName $_.ProjectName }
Posted in Development | 4 Comments

AppHarbour and Nuget and F#

While deploying an app to AppHarbour today (which I think is fantastic btw.) I came across some problems so I thought I’d document them.

1. Assembly References
with using NuGet and assembly redirects to newer versions. Basically, I had drawn a NuGet dependency on SignalR 0.4, MVC4 Beta and Json.NET 4.5.3

(Note: The assembly version is actually 4.5.0 you can read more about why the versions aren’t in sync on James Newton-Kings blog here)

This all worked fine on my machine, SignalR was happy with the using Json.NET 4.5.0 version despite it being built against 4.0.7 the problems however came when I tried to deploy to AppHarbour, my build started failing with the following messages.

ResolveAssemblyReferences:
  Unified primary reference "Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed".
      Using this version instead of original version "4.0.7.0" in "D:\temp\zm5ue1lf.ozz\input\packages\SignalR.Server.0.4.0.0\lib\net40\SignalR.dll" because AutoUnify is 'true'.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. 

It turns out that NuGet doesn’t seems to always add HintPath property to the Reference node in the project file; I have to admit that this only seems to be a problem with F# I haven’t had to do this with any C# projects yet. To fix this simply add the hint path to point to the correct path.

To do this, unload the project file and right click, and select ‘Edit project file’ then change each of the problematic references as follows

Before:

<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
      <Private>True</Private>
    </Reference>

After:

<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
<HintPath>..\packages\Newtonsoft.Json.4.5.3\lib\net40\Newtonsoft.Json.dll</HintPath>
      <Private>True</Private>
    </Reference>

2. F# 3.0 isn’t on AppHarbour

O.K I already knew this, but I have been developing this app in the visual studio 11 beta. When you create an F# project in VS11 it targets the F# 3.0 MSBuild targets file.

To fix this edit the desired project file, and find the following line

<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')" />

after this line add the following

  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />

Hope this helps!!

Posted in Development | Tagged , , , | 1 Comment