Using F# to Automate Reading–The Morning Brew


I guess most of the .NET Devs read The Morning Brew, if not you should.  It is a morning newspaper for the dev, so I end up reading it first thing when I go to work. I like to  try and automate most of the stuff . So I thought why not write a script that reads the Morning Brew feed, filter the excluded content that I am not interested in and open the urls before I come in. The reason behind using F# is I don’t have to compile the code. I could use it with FSI.exe. Incase if the extraction logic changes and I don’t have to recompile , it is just fixing the script. The best part of writing in F# is I avoid all the ceremony. Here is the F# code, it is nothing fancy. And this code can easily be modified for other link collection sites.


#r @"C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.ServiceModel.dll"
#r @"C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Xml.Linq.dll"

open System.IO
open System.ServiceModel.Syndication
open System.Web
open System.Xml
open System.Xml.Linq
open System.Diagnostics

let formatter = new Rss20FeedFormatter()
let sw = new StringWriter();
// Excluded Keywords
let exists (item:string) = File.ReadAllLines @"c:\Users\naveen\exclude.txt" |>
                             Seq.exists(fun e -> item.ToLower().Contains(e.ToLower()))

formatter.ReadFrom(XmlReader.Create "http://feeds.feedburner.com/ReflectivePerspective")
formatter.Feed.Items |> Seq.nth 0 |> fun i -> i.SaveAsRss20(new XmlTextWriter(sw))

let data = HttpUtility.HtmlDecode(sw.ToString())
XDocument.Parse(data).Descendants(XName.Get("li")) |>
           Seq.filter(fun i -> not (exists i.Value)) |>
           Seq.map(fun i -> i.Descendants(XName.Get("a"))) |>
           Seq.iter(fun x -> x |> Seq.iter(fun y ->
            try
               System.Diagnostics.Process.Start (y.Attribute(XName.Get("href")).Value) |> ignore
           with
           |ex -> printfn "Error : %s" ex.Message))

My excluded file at the moment contains javascript and jquery. I am not much into these. Here is the command line

"C:\Program Files (x86)\Microsoft F#\v4.0\Fsi.exe" --quiet --exec "C:\Users\naveen\morningbrew.fsx"

Rosetta Code – Day of the week in F#


I think the best way of mastering a language is always by solving code challenges. And here is a simple one http://rosettacode.org/wiki/Day_of_the_week and the problem is

A company decides that whenever Xmas falls on a Sunday they will give their workers all extra paid holidays so that, together with any public holidays, workers will not have to work the following week (between the 25th of December and the first of January).

In what years between 2008 and 2121 will the 25th of December be a Sunday?

Here is my solution in F#


open System
[2008..((2121-2007)+ 2007)] |>
 List.map(fun d -> new DateTime(d,12,25)) |>
 List.filter( fun d -> d.DayOfWeek = DayOfWeek.Sunday) |>
 List.iter( fun d -> printfn " %O" d)

It is very similar to Linq, but the difference between F# and C# is essence versus ceremony.

Flattening List in F# and C#


I was teaching someone F# and comparing it with C#.  I had to bring in similarities between F# and C# and one of the key things List module. I was showing List Concatenation using “@” and also showing it C#. Here is an example of using it solving with selectmany


var x = new [] {new [] {10,20,30},new [] {40,50,60}};

x.SelectMany (y => y).ToList().ForEach(Console.WriteLine);

F# Solution


[10;20;30] @ [40;50;60]

Someone threw in a challenge by asking what if the list contains values and as well as other lists. Like example


var list = new List<object>();

list.AddRange(new object [] {14,new List<int>(),new List<int>() {1,10,23}});

And here was the code someone came up with in C#

list.Flatten<int>().ToList().ForEach(Console.WriteLine);

static class Extensions
{
 public static IEnumerable<T> Flatten<T>(this IEnumerable<Object> List)
 {
 var l = new List<T>();
 foreach (var element in List)
 {
 if (element is T)
 l.Add((T) element );
 else
 l.AddRange(((IEnumerable)element).Cast<T>());
 }
 return l;
 }
}

First of all the code isn’t type safe. I know there is a better way to solve in C#, but I wanted to show how this can be solved in a terse manner with F#

And here is my solution to above problem using in F#

type  T<'t> =
 |L of 't
 |N of T<'t> list

let rec flatten l =
 match l with
 |L x -> [x]
 |N x -> List.concat(List.map flatten x)

 let tree = N[L 14;N[];N[L 1;L 10;L 23]]
 let result = flatten tree

Visual Studio Keymaps using F#


I always try and avoid using mouse, for example even for browsing internet I don’t use mouse rather I use vimperator and within VS.NET I use ViEmu. So for VS.NET I am always looking for keyboard shortcuts for the things that I cannot do through ViEmu. To do that in VS.NET I would have jump through hoops to figure out a keyboard shortcut for a command, I would have to navigate to Tools/Options/Environment/Keyboard, which is a pain.

There is also a plugin for ReSharper to do the same.

So I wanted something like the plugin, but something that I can query for. So I was planning to write one ,as a Visual Studio addin which is supposed to couple of things

  1. Pass a partial command name , which returns list of commands and their corresponding keyboardshortcuts
  2. Pass a Partial keyboardshortcut , which returns list of commands that have the keys as binding

And that’s when I stumbled upon Accessing Visual Studio’s Automation API from F# Interactive . That’s awesome and it gives the great power for automation with succinct code.

Here is the code for doing the things that I wanted to write


let convert (c:Command) = ((c.Bindings) : ?> System.Object[] |> Seq.cast<string>)

let keymapsearch key =
 myDTE.Commands |>
 Seq.cast<Command> |>
 Seq.filter(fun k -> convert k |> Seq.exists(fun k -> k.Contains(key))) |>
 Seq.map(fun k -> (k.Name, (convert k ) |> Seq.head))

let commandkeysearch c =
 myDTE.Commands |>
 Seq.cast<Command> |>
 Seq.filter( fun k -> k.Name.StartsWith(c)) |>
 Seq.map( fun k -> (k.Name, convert k ))

FYI this code has to be sent to interactive FSI window within Visual Studio .NET and to use this you would still rest of the code which is available from the original post.

And here is the usage of the above functions

commandkeysearch “Debug.Bre”

>
val it : seq<string * seq<string>> =
seq
[(“Debug.BreakAll”, seq [“Global::Ctrl+Alt+Break”]);
(“Debug.Breakpoints”, seq []); (“Debug.BreakInFile”, seq []);
(“Debug.BreakatFunction”, seq []); …]

keymapsearch “Ctrl+F5″

val it : seq<string * string> =
seq
[(“Debug.StartWithoutDebugging”, “Global::Ctrl+F5″);
(“Data.SqlEditorValidateSqlSyntax”, “Transact-SQL Editor::Ctrl+F5″)]

The automation provides REPL to VS.NET which is really handy.

Using C# Compiler as a Service in F#, PoshConsole (Powershell)


I saw this amazing video from Anders Hejlsberg on C# as Compiler service and after which, Miguel de lcaza from the Mono posted about their implementation of C# Compiler service. Thanks Miguel .The best part is ,it works out of the box in Windows on the Microsoft .NET code base. So here I am using Mono’s C# compiler code  (Mono.CSharp.dll) within Microsoft .NET Code

This is cool because we could use C# more like python. And what if VS.NET can be customized using C# based scripting ,like Lisp for Emacs.

I figured out from Miguel’s post the only class we should be consuming is Evaluator. And here is a simple extension method for string class to compile and run.

static class Extensions
{
 public static object Compile(this string code)
 {
 return Evaluator.Evaluate(code);
 }
 public static void Run(this string code)
 {
 Evaluator.Run(code);
 }
}

And here is a code that uses the above extension, which creates a Func dynamically and passes it back to static code.

static void Main()
{

 var people = new List<Person>() { { new Person() { Name = "Bush", Age = 63, Sex = 'M' } },
 { new Person() { Name = "Obama", Age = 53, Sex = 'M' } }, { new Person() { Name = "Gordon", Age = 57, Sex = 'F' } } };
 Evaluator.Init(new string[0]);
 Evaluator.ReferenceAssembly(typeof(Person).Assembly);
 "using System;".Run();
 "using System.Linq;".Run();
 "using TestPerson;".Run();
 var whereexpression = (Func<Person,bool>)"new Func<Person,bool>( (p) => p.Age < 60);".Compile();
 people.Where(whereexpression).Dump();
}
class Person
{
 public string Name { get; set; }
 public int Age { get; set; }
 public char Sex { get; set; }
}

Here is a code that uses C# within F#

open System
open System.Collections.Generic
open Microsoft.FSharp.Core
open Mono.CSharp

Evaluator.Run("using System;") |> ignore
Evaluator.Run("using System.Linq;") |> ignore

let eval code =  Evaluator.Evaluate code

let list = ["FSharp";"CSharp"]
let code =  eval "new Func<string,bool>( (s) => s == \"CSharp\") ;" : ?> Func<string,bool>
printfn "Does list contain Foo? %b" (code.Invoke("Foo"))
printfn "Does list contain CSharp? %b" (List.exists (FuncConvertExtensions.ToFSharpFunc (code)) list)

let seqCast : seq<char> = Seq.cast (eval("from x in \"Bar\" select x;") : ?> IEnumerable<char>)
printfn "Sequence result:  %b" (Seq.exists(fun x -> x = 'c') seqCast)

I know there is F# powerpack for Linq. One of the reasons we would probably extend this is, if an application is developed in F# (targeted at Devs) and it could possibly allow extensions in C#.  Here is an example ,Seesmic has platform for building extension and how would it be If I could write a “ Func<Tweet,bool>( tweet => tweet.Language == “English” && tweet.HasLink == true)”  in the search box and if the platform happened to developed in F# (which is not) it would allow the C# devs to extend it .

Another interesting use is using C# compiler service within PoshConsole . In Powershell we could use Add-Type for creating types on the fly but with is I wouldn’t have to create a class and method we could get away with just creating lambdas. Here is an example of the usage

[Reflection.Assembly]::LoadFile("D:\tools\Mono.CSharp.dll")
[Mono.CSharp.Evaluator]::Run("using System;")
[Mono.CSharp.Evaluator]::Run("using System.Linq;")
$func = [Mono.CSharp.Evaluator]::Evaluate("new Func<int,bool>( (s) => s == 10);")
$func.Invoke(100)
$func = [Mono.CSharp.Evaluator]::Evaluate("from x in new [] {100,200} select x;")
$func

Resharper Template for F#


I have been hacking F# lately and I am big fan of ReSharper. So why not create a few Live Templates for the things i do daily in F#.

Download R# live template for F#. I am sure there are few more things that can be part of this template. I have posted the code in MSDN Code gallery so that others can find and contribute.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: