Stachu.NET/blog

Pseudocode-Driven Development with F#


Posted on 12/15/2015 5:51:26 AM

... because there's nothing better than *DD acronyms, right?

Tl;dr - F# lets you write pseudocode. Once that pseudocode compiles, your program is probably right (or very close to it). (This is just another sales pitch for the |> operator)

I gave a F# hands-on lab session to a local user group a few weeks ago. The lab was heavily based on the lovely "F# Koans" program, with a rewritten test-runner. The Koans works by learning very small language features one at a time, while making unit tests pass.

You can find my rendition of the Koans here.

While learning small language features one at a time is important in making sure no one gets scared, it's extremely important to have an overarching example of why F# is great, and how we think in F#.

This is where this test comes into play:

Given a list of comma-separated strings representing stock data, the task is to find the date in which there is the largest variance in opening/closing prices.

In thinking about this problem, I understand that I want to write a function that: given a list of strings, returns a 'date' (actually a string representation of this date, to make the test pass.)

Any developer should be able to look at the following code and figure out what the intention is

let getDateForHighestVarianceInStock (data : string list) : string =
    ()

let result = getDateForHighestVarianceInStock stockData

AssertEquality "2012-03-13" result

We've essentially written pseudo-code. Code like (string list) are extremely simple to read coming from any language . Further the : string at the end of our function declaration makes it pretty explicit that we want to return a string from our function.

Currently our code doesn't compile, and that's great!

My statement at this point of the talk was (half-serious) "If we can make this code compile, the test will pass" as I've often found with F#.

At this point, we can write some very obvious pseudo-code:

let getDateForHighestVarianceInStock (data: string list) : string = 
    data
    |> skipHeaderRow
    |> projectToAFancyType
    |> orderByDifferenceDescending
    |> takeHead
    |> getTheDateFromTheRecord

As a software developer with much experience, the flow of data in this function should be somewhat obvious. All we have to do now is fill in the functions, and this is the point I want to bring home.

Many times, the fluent syntax of F# allows us to write pseudo-code in this fashion, for doing complicated algorithmic work, and come out on the other side with a clean solution.

Now that we've written our pseudo-code we have to fill in our test with some 'real' functions. The first thing we'll do is create some helper functions.

let splitCommas (x:string) = x.Split([|','|])
let parseDouble str = System.Double.Parse(str)

There have been given to us in the problem statement.

Next, we need a 'type' to hold our data in, once it's been parsed out.

type Row = { Date: string; Close: float; Open: float }

Again, F#'s syntax makes it very nice for a new F# developer to guess what's going on.

Now that we've done some pre-work, we can start making our code compile!

Remember, these are the functions we need to fill in:

|> skipHeaderRow
|> projectToAFancyType
|> orderByDifferenceDescending
|> takeHead
|> getTheDateFromTheRecord

So let's go one by one.

let skipHeaderRow = Seq.skip 1

This is simply a helper around a built-in F# function that skips the header row. Both the name and the implementation should be pretty obvious to a new F# developer.

let projectToTheFancyType rows = 
    rows
    |> Seq.map splitCommas
    |> Seq.map(fun z -> { Date = z.[0]; Close = parseDouble z.[4]; Open = parseDouble z.[1] })

Given a list of strings (string list), we want to create a (* list) of some other type, namely the Row type we defined before. To do that, we will split each of the rows by commas, and then project them into the appropriate type.

let orderByDifferenceDescending rows =
    rows |> Seq.sortBy(fun (z:Row) -> z.Close - z.Open |> abs |> (*) -1.0)

Next, we want to sort the rows, this being likely the most complicated part. if we wanted, we could create an inner function for the 'mathy' part of the algorithm, but

(z.Close - z.Open) |> abs |> (*) -1.0

should illustrate fairly cleanly that we want to take the difference and sort in a descending fashion (largest difference first)

let takeHead rows = rows |> Seq.head

Similar to 'skipHeaderRow', this is simply an alias around a built-in F# function!

 let getTheDateFromTheRecord row = row.Date

Finally, given a row, return the 'Date' part of this type.

When we put this all together we get

let stockData =
    [ "Date,Open,High,Low,Close,Volume,Adj Close";
        //...
      "2012-02-29,31.89,32.00,31.61,31.74,59323600,31.74"; ]


type Row = { Date: string; Close: float; Open: float }




let splitCommas (x:string) = x.Split([|','|])
let parseDouble str = System.Double.Parse(str)

let skipHeaderRow = Seq.skip 1

let projectToTheFancyType rows = 
    rows
    |> Seq.map splitCommas
    |> Seq.map(fun z -> { Date = z.[0]; Close = parseDouble z.[4]; Open = parseDouble z.[1] })


let orderByDifferenceDescending rows =
    rows
    |> Seq.sortBy(fun (z:Row) -> z.Close - z.Open |> abs |> (*) -1.0)

let takeHead rows = rows |> Seq.head

let getTheDateFromTheRecord row = row.Date

let result = 
    stockData
    |> skipHeaderRow
    |> projectToTheFancyType
    |> orderByDifferenceDescending
    |> takeHead
    |> getTheDateFromTheRecord

AssertEquality "2012-03-13" result

Most importantly, our pseudo-code is still in tact, and we can unit-test any part of its internals individually.


Read More

Solving Rubik's Cubes with F#


Posted on 12/27/2014 12:16:26 PM

This is a post in the series of F# Advent posts!

I couldn't contain all of my excitement into just one post... so I made a whole website, and I want to perform a community-wide experiment with the F# community (and potentially the speedcubing community).

Here's the site! fsolve.net

Comment on any blog post you see, and I'll try to answer any questions you have. Feel free to either ask questions or give tips. I'd love for this to be a go-to site for a newcomer into F#!


The idea, to be short, is to document fully my progression in solving a Rubik's Cube. Right now, I have a functional but inefficient Rubik's Cube solver.

The tl;dr version of the solver can be found here.

There's a lot of domain specific knowledge needed to understand, though, so it'd be highly beneficial to follow my train of thought at fsolve.net!

I'll be putting the source in a more organized fashion tonight when I get back from some activities :) This will also eventually be the place to raise issues or make suggestions.

Edit: HERE'S THE GITHUB!!!!

Feel free to raise any 'issues' on the repository or otherwise comment concerning confusions!


Read More

Why is it bad to pass a string array as a GET call?


Posted on 11/25/2014 7:41:46 PM

Written for a friend, but general-topic enough for a blog post.

To give you a bit of background:

The internet is just a bunch of "Requests" and "Responses."

A client (aka a web page or your javascript) makes REQUESTS to a server. That server processes the Request, does some stuff, and returns some sort of Response.

Parts of a Request.

Just like there's a basic structure to an HTML page (<head> and <body> nodes sitting in a big ol' <html> node), there is structure to an HTTP Request. As I see it, there are four main parts to a web Request:

  1. URL. This is literally a Universal Resource Locator. it is used generally as a means to hit a specific part of your web server.
  2. HTTP Verb. These verbs are used as indicators to the Server as to WHAT the server should do. I'll dive into these more later.
  3. Request headers. This is additional metadata that a Client provides a Server in order to make the Request go through. This is commonly used to pass back and forth data like usernames, passwords, API Keys, content types (whether you're giving the server JSON data or XML data, etc).
  4. Request body. This is often the fattest part of your Request, and its use is to hold the data that the server needs.

More on HTTP Verbs

The most common HTTP Verbs are GET and POST.

Without standards, the ability to communicate on the internet would become hell very quickly, so we've defined these Verbs to each have a specific action.

GET Requests

are used to simply get data. Literally. You pass a URL to the server, maybe with the ID of the record you want to grab, and it does the work. You'll get a Response of a bunch of data, one examble being a list of People in a JSON format.

POST Requests

are used to give data.

Let's say you want to turn a bunch of users to some "inactive" state. One way you could do this would be to post or give an array of UserIds that I want this action performed on. I would POST this array to the server as a Request, so it could DO things.

Typically, the Responses that I expect from a POST are a boolean indicating "things went well!" or "things went poorly :(" but it could be more complicated than that, returning an array of errors. [For example, if I post a phone number, I might get ["Phone numbers cannot be 800-numbers", "Phone number invalid"], etc

tl;dr

GETs should get data, and shouldn't do any "math." They're like printing a document. Once it's out, you can't edit the copy in the computer any more.

POSTs, by contrast, should DO things, and maybe emit a response from it.


Read More

SignalR is Really Cool


Posted on 9/29/2014 6:37:34 PM

At my previous job, I worked on my school’s web team working on wcupa.edu.

Everything was great; I loved the atmosphere, the people working there, the hours, etc., but I knew that there was one thing that felt just wrong about it. I didn’t know what it was at first, but eventually I figured it out:

I really don’t like ASP.NET WebForms.

WebForms has a place and time, of course, and for what the school’s website was doing it was more than applicable. In fact, I would reluctantly suggest that it would be the best .NET solution for the job. It’s a file-based site that needs the ability for a bunch of people to be able to edit their pages without .NET experience. What bothers me, though, is the feel of WebForms. It’s trying to make you think you’re just coding a regular piece of software when you’re really working on the web. While this sounds nice in theory, I don’t think the current model does a good job of hiding the fact that it’s on the web. Instead, the abstractions always hurt me. I remember the days of trying to figure out how to deal with ‘state’ in a WebForms project. It’s disgusting.

Then I met ASP.NET MVC.

After work and in between classes, I watched probably five hours of Pluralsight before I typed anything relevant to it. I was stuck. Many of those projects where I thought “enh, this would be horrible to implement” suddenly made sense in an MVC world. I became energized with the taste of MVC, and my love of web development doubled over the course of a week.

I quickly rewrote stachu.net from scratch in MVC, just to play. It was a good start, but not enough. I then played around with a few CRUD applications, following along with a few PluralSight courses and read through a few chapters of the ASP.NET MVC Apress book (perfect book, by the way!).

I kept studying and learning until I got my current job as an MVC developer, in fact!

Obviously, none of this has had anything to do with SignalR. My point, though, is that by discovering MVC, so many things started making sense to me. I had lots of new ideas for projects and I became totally reenergized to work on personal projects.

This past weekend at a PhillyDotNet CodeCamp, I attended Chris Gomez‘ SignalR talk. I’ve looked briefly into SignalR before, and even attended an introductory lecture on the subject, but for some reason this session hit me pretty hard. Just like when I first got into MVC, I started thinking of so many ideas. Most of them were dumb, but I got a few pretty cool ideas down.

I’m looking forward to January when I can explore some of these ideas. Maybe once I get a bit more experience I can throw SignalR around at work, if it becomes applicable.

Thanks, Chris! Great session, definitely made things click for me!


Read More