Tuesday, June 30, 2015

The F# Beginner

I'm an experienced software engineer (employed as a software architect). I'm passionate about learning new languages and technologies. I've decided to learn F# as my next endeavor and I thought I'd blog about the experience. After all, there are plenty of tutorials available, but there aren't very many blogs that record the process of going from noob to competent in a new technology.

The goals of this blog are:
  1. Learn F# and document the process.
  2. Provide tutorials from the perspective of a non-expert. I hope this might be more accessible to other learners.
  3. Reflect on the process of learning a new technology, including the frustrations and victories. 
  4. Experiment with this docu-tutorial blog format.
  5. Solidify what I'm learning by forcing myself to document it.
The intended audience:
  1. Other coders who are interested in learning F#. 
  2. I'll be assuming a certain basic knowledge of programming concepts. If you're an absolute beginning coder, this probably isn't the place to learn.
  3. People who are interested in the learning process in general.
Blogger isn't my favorite blog platform (by far) but it's got a few advantages for this project. Since this is primarily an experiment, I don't want to invest much time in getting things set up. 

Monday, June 29, 2015

Getting Started

Okay, so I've decided to learn F#. Why did I choose this language?
  • Functional. 
    • I use JavaScript a lot and I've come to really enjoy the power of functional programming. I found myself using lambdas a lot in some C# I was writing for work and thought to myself "I should really check out that functional language Microsoft sponsored."
  • Different.
    • F# has a distinctly different syntax from the languages I use often (Python, Java, C#, JavaScript). I thought it would broaden my mind to wrap my head around this syntax.
How am I going to attack this process? It probably makes sense to have a strategy. Here's what I'm thinking:
  1. Read something to learn the syntax and concepts.
  2. Try some examples.
  3. Create a project to exercise the new skills.
  4. Blog about it.
So the very first thing I need to do is get F# installed. I'm not going to go into detail on this (check the link for your platform) but I will reflect on a few items. 
  1. I'm on OSX. F# is part of the .NET family of languages, but this isn't a problem. The mono framework provides good support for F#, which is an open-source language. Bottom line: you don't need to be on Windows to work with F#. I plan to do this entire project on OSX.
  2. Xamarin Studio is a decent .NET IDE on OSX, and also supports F#.
  3. Visual Studio Code also provides decent support for F# on Mac.
  4. The mono framework, which I already have installed, includes the command line compiler and interactive shell.
I've decided that in general I plan to use Visual Studio Code and the command line compiler for this project. I may try out some other IDE's at some point, but certainly in the early stages I'll work with the leanest tools available. If you want to follow along, you can install Visual Studio Code and mono, which is exactly what I'll be using.

GOTO Command Line Tools

Sunday, June 28, 2015

Command Line Tools

Okay, so I'm going to start by inspecting the command line tools for F#. This depends on whether you're using .NET or mono. For mono:

fsharpc == command line compiler
fsharpi == command line interactive (REPL)

For .NET:

fsc.exe == command line compiler
fsi.exe == command line interactive (REPL)

So I'll start by messing around with the interpreter. A REPL is a hugely beneficial tool when learning a language or trying out code you don't understand. It won't take me too far, because doing anything complicated requires more flexibility, but it's a great way to test understanding. 

I'm also going to use the tutorials over at Try F#. You can do the same if you like. Okay, I'm ready to learn some basics!

Matthews-MacBook-Pro:~ Matthew$ fsharpi

The REPL tells me I can get help with the command #help;; so I'll try that first. Here are a few fundamentals of the REPL:
  • Every statement or block needs to be followed with ;;. This tells the REPL to process the command. This doesn't seem to be part of the language,  just a convention of the interactive F#.
  • The REPL responds to commands that start with a hash mark. It took me a minute to figure this out, because I didn't use #help;;. Be smarter than me and use the help menu!
    • #help;;  Access the help menu. 
    • #quit;;  Quit the REPL.
    • #r "File.dll";;  
      • Assuming that the "r" stands for reference; allows you to reference a dll. I'll take that for a spin.
    • #I "path";;  
      • Looks like you can add a path to include dlls. 
    • #load "file.fs" ...;; 
      • If I want to load a script and then play around with it in the REPL, this command should do that for me.
    • #time ["on"|"off"];; 
      • No idea.  Maybe this gives you stopwatch data about the executing code?
I'm curious about that #time;; option so I'll try that first. 

> #time "on";;

--> Timing now on

> let me = "spotaneous";;
Real: 00:00:00.000, CPU: 00:00:00.003, GC gen0: 0, gen1: 0

val me : string = "spotaneous"

That's pretty cool! So I can do some primitive optimization in the REPL by comparing the timing of different code options. It's not something I need right away, but cool nonetheless.

It's worth noting that this is how the REPL reports the value of a reference:

val me : string = "spotaneous"

It looks a little confusing to me, since it looks suspiciously like a variable assignment in another language, but it's not. I can check the value referenced by:

> me;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0
val it : string = "spotaneous"

Saturday, June 27, 2015

Command Line Tools: Referencing DLL Interactively

Continuing with my investigation of the F# command line tools, I'm interested in exploring a couple of options: referencing a dll and including an F# script in the REPL. Let's start with a dll...

I'm going to use the FileDB dll from CodePlex. I honestly don't know anything about this project, but it looks like it should make for a good example. It's written in C#, and I guess I'll also stumble through calling C# from F#. Should theoretically be an easy thing.

First:

> #r "FileDB.dll";; 
--> Referenced '/Users/Matthew/Desktop/FileDB.dll' (file may be locked by F# Interactive process)

Okay, well that looks promising! By the way, I've got the REPL in the working directory with the FileDB.dll. Okay, so now let's see if I can get anything working. The internets tell me that open is the way to reference a .NET namespace in F#. 

> open Numeria.IO;;

Okay... Well, that gave me no output.  Let's see if I've got a class there someplace:

> FileDB;;

  FileDB;;
  ^^^^^^

/Users/Matthew/Desktop/stdin(3,1): error FS0803: Invalid use of a type name and/or object constructor. If necessary use 'new' and apply the constructor to its arguments, e.g. 'new Type(args)'. The required signature is:
FileDB(fileName: string, fileAccess: System.IO.FileAccess) : unit.

Whoa, interesting. So obviously there's something backing FileDB or I think I would get an error like this:

> BlahDB;;

  BlahDB
  ^^^^^^

/Users/Matthew/Desktop/stdin(4,1): error FS0039: The value or constructor 'BlahDB' is not defined

So that's good! Let's try to create an empty db file. The FileDB documentation tells me that you would do this like so in C#:

var pathDB = @"C:\Temp\MyDB.fdb";

// Creating an empty FileDB archive
FileDB.CreateEmptyFile(pathDB);


So I'll try what I think is the right way in F#: 

> FileDB.CreateEmptyFile "Blah.db" ;;
val it : unit = ()

Worked!


Friday, June 26, 2015

Command Line Tools: Loading a Script Interactively

Last post, I loaded a dll in the interactive shell (REPL) and called a method. This time, I want to explore a similar option: loading code from an external script. I've got a script adapted from the examples on http://www.tryfsharp.org/ and I'll use that for my example.

The questions I'd like to answer for myself:

  • How do I load an external F# script and call methods on it in the REPL?

I've got this saved in fsharp.fs:

// This code is saved in fsharp.fs
// "Date,Open,High,Low,Close,Volume,Adj Close"
let stockData =
    [ 
      "2012-03-30,32.40,32.41,32.04,32.26,31749400,32.26";
      "2012-03-29,32.06,32.19,31.81,32.12,37038500,32.12";
      "2012-03-28,32.52,32.70,32.04,32.19,41344800,32.19";
      "2012-03-27,32.65,32.70,32.40,32.52,36274900,32.52";
      "2012-03-26,32.19,32.61,32.15,32.59,36758300,32.59";
      "2012-03-23,32.10,32.11,31.72,32.01,35912200,32.01";
      "2012-03-22,31.81,32.09,31.79,32.00,31749500,32.00";
      "2012-03-21,31.96,32.15,31.82,31.91,37928600,31.91";
      "2012-03-20,32.10,32.15,31.74,31.99,41566800,31.99";
      "2012-03-19,32.54,32.61,32.15,32.20,44789200,32.20";
      "2012-03-16,32.91,32.95,32.50,32.60,65626400,32.60";
      "2012-03-15,32.79,32.94,32.58,32.85,49068300,32.85";
      "2012-03-14,32.53,32.88,32.49,32.77,41986900,32.77";
      "2012-03-13,32.24,32.69,32.15,32.67,48951700,32.67";
      "2012-03-12,31.97,32.20,31.82,32.04,34073600,32.04";
      "2012-03-09,32.10,32.16,31.92,31.99,34628400,31.99";
      "2012-03-08,32.04,32.21,31.90,32.01,36747400,32.01";
      "2012-03-07,31.67,31.92,31.53,31.84,34340400,31.84";
      "2012-03-06,31.54,31.98,31.49,31.56,51932900,31.56";
      "2012-03-05,32.01,32.05,31.62,31.80,45240000,31.80";
      "2012-03-02,32.31,32.44,32.00,32.08,47314200,32.08";
      "2012-03-01,31.93,32.39,31.85,32.29,77344100,32.29";
      "2012-02-29,31.89,32.00,31.61,31.74,59323600,31.74"; ]

let splitCommas (x:string) =
    x.Split([|','|])

let processStockData sData =
    sData
    |> List.map splitCommas
    |> List.maxBy (fun x -> abs(float x.[1] - float x.[4]))
    |> (fun x -> x.[0])

Now, in theory, I should be able to load this script and call either of the functions that have been defined here. I haven't done this before, but let's give this a try. The help menu says this:

#load "file.fs" ...;; Load the given file(s) as if compiled and referenced


Okay, so in theory I should be able to do this:

> #load "fsharp.fs";; 
[Loading /Users/Matthew/Desktop/sharp.fs]

/Users/Matthew/Desktop/sharp.fs(2,1): error FS0222: Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.

Oops. Well, that didn't quite work. The internets tell me slightly more than this verbose error message. I'm going to add a module statement at the top of the fsharp.fs file:

module Fsharp

And now let's try it again:


> #load "fsharp.fs";;
[Loading /Users/Matthew/Desktop/sharp.fs]

namespace FSI_0006
  val stockData : string list
  val splitCommas : x:string -> string []

  val processStockData : sData:string list -> string

Looks like that worked. It's worth noting that at this point I really have only the vaguest notion of what either module or namespace mean in the context of F#. Of course, my experience with other languages give me some pre-conceived notions but in the case of F# I'm just taking this on faith. I think this is an important concept in learning new technology: don't let not knowing get you stuck. The distinction between these ideas will become clear in time. For now, I'm focused on getting the REPL to include an external F# script...

Now the moment of truth:

> processStockData stockData;;

  processStockData stockData;;
  ^^^^^^^^^^^^^^^^

/Users/Matthew/Desktop/stdin(13,1): error FS0039: The value or constructor 'processStockData' is not defined

Oof, not defined. Well, it said when I loaded the script that processStockData was defined, but I'm guessing it's nested inside of the namespace listed above. Okay, so I've got to figure that out. I've got a hunch:

/Users/Matthew/Desktop/stdin(14,1): error FS0039: The namespace or module 'Fsharp' is not defined
> Fsharp.processStockData stockData;;

  Fsharp.processStockData stockData;;
  -----------------------^^^^^^^^^

/Users/Matthew/Desktop/stdin(15,24): error FS0039: The value or constructor 'stockData' is not defined

Hey, look at that: Fsharp is the name I gave the module, and I used that to prefix the method and now it's complaining about missing stockData. So it stands to reason that I should be able to prefix that as well:

> Fsharp.processStockData Fsharp.stockData;;
val it : string = "2012-03-13"

Boom! You can work through the original tutorial yourself but I can tell you that "2012-03-13" is the expected output.

So this session answered a few questions but raised a few others:
  • What's the difference between a module and a namespace?
  • How do you import a namespace into the current namespace?
  • What are the best practices for handling modules vs. namespaces? Naming conventions?
GOTO


Thursday, June 25, 2015

F# Modules

The question I want to answer in this post:
  • What's the difference between a module and a namespace?

Modules

Ok, let's start with the concept of a module. Here's the official Microsoft documentation on the topic: https://msdn.microsoft.com/en-us/library/dd233221.aspx. I found this particularly enlightening:
It [module] is implemented as a common language runtime (CLR) class that has only static members.
So think of it in the context of C# and it would look something like this:

class Blah 
{
    public static void Foo() { Console.WriteLine("Foo!"); }
}

That's a totally familiar concept, and it would look something like this (?) in F#:

module Blah

let Foo = fun () -> printfn "Foo!"

ASIDE: This example has brought up a new question, and something I stumbled over. Why doesn't this work?

let Foo = printfn "Foo!"

The reason is because this is actually setting Foo to the result of printfn "Foo!", which is val it : unit = (). So we need to make it clear that we're setting Foo to be a function, provided by the fun keyword, otherwise the compiler doesn't understand. This isn't a problem when you provide parameters, because the compiler can infer that you're creating a reference to a function.

UPDATE: Okay, as I've continued to learn I've gotten some more insight on this behavior. So the easier, possibly more "proper" way to do this is to use unit to represent the missing parameter:

let Foo () = printfn "Foo!"

This looks suspiciously like a function definition from a non-functional language, but it's not. And when you call the function, you've got to pass a unit as a parameter or it thinks you're just referencing the function:

// Not calling the function, just referring to it
> Foo;;
val it : (unit -> unit) = <fun:it@117-30>

// Function call taking a parameter of type unit!
> Foo ();; 
Foo!

val it : unit = ()

Ok, back to modules. There are apparently two kinds of module declarations: top level and "local":
  • Top level declarations mean that the whole file is in the module. The module declaration also needs to be the first declaration in the file.
  • Local modules means that you can have more than one module in a file. It's a little different than the top level module.
//Notice the identation!
module Blah1 =
    let Foo = fun () -> printfn "Foo!"

module Blah2=
    let Foo = fun () -> printfn "Foo2!"

I think that makes sense. Next rule:
  • If you don't use a top level module declaration, F# will insert one for you with the same name as the file, first letter uppercased. However, it will only do this if:
    • You're creating an exe and not a dll.
    • You've got a single file.
    • You're not including the file as a library.
  • So basically, if you're making a library you have to create a top level module or namespace.
I tripped over this rule when I tried to import a file in the REPL in a previous post. I had to go in and add a module declaration, remember?

Apparently you can also set an accessibility modifier, but I'm not going to mess with that right now.

Modules can also nest. So this is legal:

//Notice the identation!
module Blah1 =
    let Foo = fun () -> printfn "Foo!"

    module Blah2=
        let Foo = fun () -> printfn "Foo2!"

You should also notice that we've got the function Foo in Blah1 and again in Blah2. These are distinct Foos since they're in different modules and there's no name collision.

Alright, so I think I'm getting the hang of modules. Now...
  • What's the difference between a module and a namespace?
See Also:

F# Namespaces

F# Namespaces

In the previous post I tried to figure out modules, and I think I've got a decent grasp of that now. In this post, I want to do the same for namespaces.

Again, I'm teaching myself this aspect of F# by referencing the Microsoft documentation on the topic.

So a quick rundown on the module concept as a recap:

  • Modules remove members from the global namespace.
  • Provide top-level modules and local modules.
  • They can be nested.
  • Are implemented as a class with static methods.
  • Can contain members directly.
In contrast, a namespace:
  • The first declaration in the file must be the namespace.
  • Cannot contain members directly. 
  • Can contain types and modules.
  • Can be declared implicitly as part of a module declaration.
  • Can be nested (but slightly different syntax from modules).
  • Namespaces can span multiple files.
So this makes a lot of sense if you think of it from the perspective of C#. A module is just a class with static members. A namespace is a namespace, just like you would expect in C#.

Example time. Explicit namespace declaration:

namespace Meow

module One =
    let time = 40

Implicit namespace declaration:

module Meow.One

let time = 40

You can also nest namespaces:

namespace Meow

// Some code

namespace Meow.Blah

//  More code

Well, that seems pretty straightforward now that I understand what's going on. Next question:
  • Ok, now I've got modules and namespaces, but how do I include them in another file?
The answer is:

// Let's import a core framework component:
open System.IO

There are a few potential side effects for how F# handles ambiguities between the namespaces. The documentation says:
The F# compiler does not emit an error or warning when ambiguities occur when the same name occurs in more than one open module or namespace.
I tried this and I got the following errors:


> open List;;

  open List
  -----^^^^


/Users/Matthew/Desktop/stdin(51,6): error FS0892: This declaration opens the module 'Microsoft.FSharp.Collections.List', which is marked as 'RequireQualifiedAccess'. Adjust your code to use qualified references to the elements of the module instead, e.g. 'List.map' instead of 'map'. This change will ensure that your code is robust as new constructs are added to libraries. 

This makes me think that there was probably a change in this rule since the documentation was last updated.

So I'm pretty sure that this answers all of my immediate questions about modules and namespaces in F#. I'm sure I'll have more as I continue learning, but for now I feel like I've got the concepts.

See Also:

F# Modules

Wednesday, June 24, 2015

F# Naming Conventions

One of the questions that I want to answer about namespaces and modules is this:
  • What are the proper naming conventions for F#?
I found a pretty authoritative-sounding answer here and here. To summarize:
  • PascalCase for most everything.
  • camelCase or PascalCase for let values and parameters.
That's simple enough!