Fun Friday – Diamonds are Forever

Sometimes you write code you’re just not super happy with.

The Diamond Kata is a simple kata to take a single character parameter, and return a “diamond” shaped string.  Examples:

diamond 'A';; 
val it : string = "A"

diamond 'B';;
val it : string = "
 A 
B B
 A "

diamond 'C';;
val it : string = "
  A  
 B B 
C   C
 B B 
  A  "

etc;;

That’s how I describe this Kata I was working on. I’m just not super happy with it. It feels wordy, and a bit inelegant. Still, it does work (as long as you pass a character ‘greater’ than upper case A. I should probably enforce that sometime… but for now, here it is.


open System
let diamond char =
let chars = [ 'A' .. char ]
let numberOfChars = List.length chars
let padCount i = numberOfChars (i + 1)
let gridWidth = numberOfChars * 2 1
let pad i = new string (' ', i)
let init = chars |> List.mapi (fun i c -> (string c), (padCount i))
let all = init @ (List.tail (List.rev init))
let makeLine (str,padCount) =
match gridWidth (padCount * 2 + 1) with
| 0 -> pad padCount + str + pad padCount
| a -> pad padCount + str + pad (a 1) + str + pad padCount
all |> List.map makeLine
|> List.reduce (fun x y -> sprintf "%s%s%s" x Environment.NewLine y)

view raw

Diamond.fsx

hosted with ❤ by GitHub

TDD in Fable and React – can it be done?

I’ve been working to evangelize F# through {Redacted} for about a year now. I started with tests, and the build server, using FAKE and using standard tools.

In one of our Dev org meetings today, a junior developer brought up his experience with Fable, after noting how much fun I was having and sharing while coding in F#.

His review was fantastic. He was using React, and comparing native Javascript versions to what F# was enabling him to produce, and the code was more terse and wonderful. One of the things you immediately notice about React components is that the markup is still quite messy, and there is certainly something “icky” feeling about combining your markup and javascript. With Fable, Elmish and React, you are simply calling functions, with no extra tags that you don’t need.

Fundamentally though, the debugging story wasn’t great, and the TDD story was equally difficult, as he couldn’t figure out how to immediately test against a virtual DOM in his Fable F# code. For now, I ask the community, how do you best do that? How do you test that the virtual DOM actually contains the react component in question? How do you test it? I have a feeling that in the next week or so, I’ll find out.

Modeling the Domain : Short Codes

Anyone who’s read For Fun and Profit’s domain modeling exercise may see some similarities in today’s code. Mainly, I wanted to point out the value of quickly being able to create types that describe my functions here.  For context, I’m in the middle of rewriting a sticky report that consumes data from a ton of different places… this is an example (slightly modified, to avoid spilling too many of {Redacted}’s beans.)


type ShortCode = private ShortCode of string
type ProductShortCode = private ProductShortCode of ShortCode
type AccountShortCode = private AccountShortCode of ShortCode
module ShortCode =
let create s =
if System.String.IsNullOrEmpty s then None
elif s.Length > 15 then None
else Some (ShortCode s)
let value (ShortCode s) =
s
module AccountShortCode =
let create s =
match ShortCode.create s with
| Some sc -> Some (AccountShortCode sc)
| None -> None
let value (AccountShortCode (ShortCode s)) = s
module ProductShortCode =
let create s =
match ShortCode.create s with
| Some sc -> Some (ProductShortCode sc)
| None -> None
let value (ProductShortCode (ShortCode s)) = s

view raw

ShortCode.fsx

hosted with ❤ by GitHub

In the above, we’re dealing with a thing called ‘Short Codes.’ At redacted, we have a shortened string which represents many of our more common domain objects, called a ‘Short Code’ which makes domain objects easily identifiable when viewed in spreadsheets.

In C# code, we’ll typically treat these objects as simple strings, or you deal with of domain types as espoused in Vladir Khorikov’s Pluralsight course, “Applying Functional Principles in C#”.

But in F#, you get drastically simpler code, that gives you similar benefits.

  1. Any change to ShortCodes can be done once, and all references using it get the change. That’s as DRY as it comes.
  2. ShortCodes can be equal to each other, but AccountShortCodes cannot be equal to ProductShortCodes cannot be (try it in FSI, you get compiler errors!)
  3. The modules allow us to retain the business logic, so we avoid the annoying issues of duplicating validation code everywhere. If I reference an AccountShortCode, it’s implied that I created one successfully in the first place!

The code to do stuff becomes quite easy:

type ConsumingRecord = { ShortCode : AccountShortCode
                         ImportantValue : decimal }

let m = AccountShortCode.create "APPLE";;
// m is an AccountShortCode option, because of the 
// validation logic there, so we need it from the option, 
// before we push it into our consuming type.

let n = { ShortCode = (Option.get m)
          ImportantValue = 5.0m}

The subtle thing here is that we have to actually deal with the fact that it’s an option. We CAN fail to get an AccountShortCode here, depending on what we pass in, but once we have a “ConsumingRecord” object, the validity of the ShortCode is guaranteed. This only works, however, because F# doesn’t do nulls. Once your language does nulls, it throws this stuff right out the window.

But I’m sure eventually C# will get that, too. You’ll just have to use an attribute to make your class less C-sharpy. 😉

Not Much F# Today

You ever have one of those days when everything goes wrong and it’s all a C# developer’s fault? I kid, of course, but it made for a difficult day with almost no sitting at my own desk to actually get anything done.

My mission is to update this blog every day, regardless of what I actually accomplish for the day. Today, I saved the world, and solved problems that were a little more tactical in nature. I did enjoy a welcome to the firm lunch with a new QA in the office, but beyond that, very little coding.

Fun Friday – Roman Numeral Kata

Roman numerals are about the most useless things on the planet nowadays, provided you aren’t rolling credits at a movie screen.

However, if the Romans DO return, we have a solution to the pesky number problem. I present you my F# implementation.


let vals = [(1000, "M");(900, "CM");(500, "D");(400, "CD");
(100, "C");(90, "XC");(50, "L");(40, "XL");
(10, "X");(9,"IX");(5,"V");(4,"IV");(1, "I")]
let toRoman iVal =
let rec loop acc n list =
match list with
| [] -> acc
| (i, s)::xs when n >= i -> loop (acc + s) (n i) list
| x::xs -> loop acc n xs
loop "" iVal vals
let fromRoman sVal =
let rec loop acc (str : string) list =
match list with
| [] -> acc
| (i, s)::xs when str.StartsWith(s) -> loop (acc + i) (str.Substring(s.Length)) list
| x::xs -> loop acc str xs
loop 0 sVal vals

I endeavor to explain for those not yet converted to the F# happy-path.

The first lines (1-3), declares a value (“vals”) as a list of tuples. Those tuples consist of a number, and it’s equivalent textual value in the Roman Numeral form. The ordering is important, as it goes from largest numerical value to smallest in the list.

Both functions defined here (toRoman and fromRoman) are very similarly designed. They start with a single parameter, and then define and internal looping function that actually creates the resulting value. Then they call that internal function with an “empty” accumulator, the initial parameter value, and the vals list declared above. If you run a simple test in FSI with these functions you should easily get some good results:

> toRoman 54;;
val it : string = "LIV"

> toRoman 2017;;
val it : string = "MMXVII"

> fromRoman "MMXVII";;
val it : int = 2017

Internal loops with an accumulator are common in functional code. Our loops use the “acc” (aka, accumulator) parameter to sum up the matching numbers in the fromRoman function, and to build the resulting string in the toRoman function. The internal loop  matches the incoming list, and compares it against 3 possible options. The first possible match is against an empty list. If the list passed in to the loop function is empty, it simply returns the acc value. The second match is a list with the head of the element deconstructed as a tuple (i, s), filtering when the “n” parameter (of the loop function) is larger than (or equal to) the “i” value in the tuple. In that case, we simply call the loop function again, appending the s value to the acc parameter, subtracting the i value from the n parameter, and passing the same list into the function again. Finally the third option is when it’s just a simple list object that has a head and a tail (the match order counts) and it passes the existing acc and n parameter values to the loop function with the tail of the list.

When I pass in 54 into the toRoman function, the first thing that happens in that function is:

1) The loop function is defined and then called, with “” as the acc parameter, 54 as the n parameter and the vals list [(1000, “M”)…(1, “I”)] as the list parameter.

2) The loop executes, matching against the list parameter.

3) The list is not empty, so it skips the first match.

4) The first value in the list (1000, “M”) is capable of being represented as a tuple (i, s), and the list itself matches the cons operator (“::“) as well, but the “when” setting n >= i does NOT match, because the n parameter is 54 and the i is 1000, so it skips the second match.

* Reread and, make sure you understand this part, as it’s the critical point of the function.

5) The final option matches, and calls loop again, this time with parameters: acc = “”; n = 54, and list = [(900, “CM”)…(1, “I”)] 

6) The steps 3-5 execute again. The head of the list is compared, until eventually the “n” parameter is larger or equal to the corresponding “i” (from step 4).
(900, “CM”) -> Nope
(500, “D”) -> Nada
(400, “CD”) -> No Dice


(50, “L”) -> That’s a match!

7) Since that match occurred, we STILL loop through the execution, but now we modify our parameters a bit. Instead of the plain old acc, now we apply a function to the acc to accumulate the value; acc is no longer “”, it is now “” + “L”.  The variable n is modified as well. It is no longer 54, it becomes (54 – 50). The list value stays the same [(50,”L”)…(1, “I”)].

8) The new values are now matched, and the process continues. The list is still not empty, and the new n value (4) is clearly less than 50 (the first element in the list), so we move on through the list, in the same way we did before but against the new n value (4):
(50, “L”) -> Nope
(40, “XL”) -> Negative
(10, “X”) -> No Dice
(9, “IX”) -> Sorry
(5, “V”) -> Not quite
(4, “IV”) -> Yep!

9) The result updates acc to “LIV”, and n to 0. We loop through the remaining 2 items in the list (4, “IV”) and (1, “I”) and get to the last possible match [], the empty list.  The last match returns the acc passed in (“LIV”). That becomes our final value, and is the result of our toRoman function.

The differences between fromRoman and toRoman are simply related to the data types involved. String “subtraction” doesn’t work with a simple minus sign (at least, not without defining a new infix operator), so instead it’s “str.Substring(s.Length).” String comparison doesn’t work with the >= operator, so str.StartsWith(s) was recruited to do the job. Everything else largely works the same, the accumulator accumulates the values while the function executes and the str variable is “decremented”, until the list is exhausted.

There are some clear flaws in my implementations here, and I accept them for what they are. Firstly, in the toRoman function, negative value parameters all return an empty string. I don’t remember my mathematics history there, and I am not sure if they even actually had the concept of negative numbers back then. If you are a history buff, and know the answer, please comment and let me know. Secondly, the fromRoman function isn’t validating the incoming text. You could submit something things like “CDCDCD”, and it would return 1200, even though the input is clearly wrong. Finally, when you put in an exceptionally large number into toRoman, you can end up with a LOT of “M”s, simply because the vals list doesn’t contain enough “domain knowledge” about larger numbers.

Still, it largely works, so for a Fun Friday, I’m happy with it. Enjoy!

Quick ADO.NET in FSI

This morning, a user came to me with a nasty problem. At {Redacted}, we have an application which shows Account Data, one account at a time called AccountView. It’s an app that was developed years ago, which functioned admirably, but given {Redacted}’s success, the one at a time nature of the application is showing it’s age. But, like many enterprise apps in the world, we’ve just let it go on, figuring we’ll eventually get it to.

See the application is a simple one that shows a simple drop-down list of accounts, and allows the user to select one. Once selected, it fills up 3 grids with various tables after executing a fairly complex stored procedure with the selected account’s identifier as a parameter.  That stored procedure performs some pretty weighty calculations.

Still, my user came with a nasty issue. 2000 accounts had been audited, and she needed a simple sum of values. As far as she knew, the only way to get that data would be to use AccountView and hit each account, copy the grid data, sum it up, and then put it in a spreadsheet.  She was estimating about a week of doing this, and cross-checking it.

I did it using F# and Ionide in VS Code in about 20 minutes. I show it here, leaving out any proprietary bits that may cause {Redacted} to have a fit. Here’s the code. Hopefully it helps you out in your next “hey can you get me a ton of data that requires a stored procedure to get at” adventure.


open System
open System.Data
open System.Data.SqlClient
let bigGrossQuery = "SELECT c.id, c.accountName
FROM dbo.accounts AS c
WHERE c.accountName IN
( << A GIGANTIC LIST OF ACCOUNTS >> );"
let connectionString = "Server=myserver.redacted.org;
Database=MY_BACKUP_DB;
Trusted_Connection=True;"
let queryForAccounts() =
use conn = new SqlConnection(connectionString)
use command = new SqlCommand(bigGrossQuery, conn)
command.CommandType <- CommandType.Text
conn.Open()
let reader = command.ExecuteReader(CommandBehavior.CloseConnection)
[while reader.Read()
do yield (reader.GetInt32(0), reader.GetString(1)) ]
let executeSproc (accountId : int) =
use conn = new SqlConnection(connectionString)
use dataAdapter = new SqlDataAdapter()
use command = new SqlCommand("mySproc", conn)
let param = SqlParameter("@id", SqlDbType.Int)
let dataSet = new DataSet()
command.CommandType <- CommandType.StoredProcedure
param.Value <- accountId
command.Parameters.Add(param)
|> ignore
dataAdapter.SelectCommand <- command
conn.Open()
dataAdapter.Fill(dataSet)
|> ignore
let filtered = dataSet.Tables.[1].Select("myFilter = 1")
filtered
|> Array.sumBy (fun a -> System.Decimal.Parse(a.["summable_column"].ToString()))
let main filePath =
let accounts = queryForAccounts()
let lines = accounts
|> List.map (fun (id, name) ->
let result = executeSproc id
sprintf "%s,%f2" name result
)
|> List.toArray
System.IO.File.WriteAllLines(filePath, lines)
main @"\\server\file.csv"

view raw

GetSqlData.fsx

hosted with ❤ by GitHub

A Random Thought…

I was driving home last night, near the 124th street exit, and an older-looking Honda Civic merged in front of me. When the driver turned on his blinker, indicating the merge, I noticed the blinker was blinking decidedly faster than the average blinker on the freeway at that time. I became annoyed at this, and genuinely thought less of this random driver for his “spastic blinking.” I even made a face, indicating my displeasure. Self-awareness came when I noticed the grumpy frown in my rear-view mirror.

I fear lunacy, as I’m sure anyone would, given the circumstances.

Taking Friday Off

Honestly, I’m not a big “take the day off” sort of guy. I’m a workaholic. I define myself by what I do. I code… I sit in a little room, listen the heavy metal music, and write the best code I can. (And yes, it’s awesome code.) Still, a friend of mine said “your kids don’t care about your project right now…” so Friday, was to be my day off.

It started with a day in the mud. We awoke, and we went out to the South 47 farms, where apparently, someone had ordered 50 tons of mud spread around the place. We did the farm tots experience, and I can now say, that 2009 has involved the requisite minimum hay ride count. The same can be said of corn mazes. Picking pumpkins concluded our farm experience, and Lydia was the only child who picked a pumpkin that actually weighed less than herself.

The remainder of the day was fairly lounge-worthy. An early chicken dinner gave way to the carving festivities. Zoe and I spent the first of our carving time cleaning off 4 pounds of mud from the pumpkins, and by the time we’d completed them, Lydia and Heather had completed the tiny “princess pumpkin.” Emerson had fallen quite deeply to sleep while Heather and Zoe dug through pounds of seedy innards. Zoe’s pumpkin had a distinct “Scary Sloth from Goonies” sort of appeal, while Emerson’s was a classic “semi-toothless” grin.

The evening ended with a quick family movie night. We’d been going with the classics… Star Wars, Wizard of Oz, but this time, we tried more a “modern classic”, watching The Neverending Story. That movie brings fond memories for any child of the 80s, but there is a distinct campiness there. A REALLY distinct campiness. It’s a campiness that’s almost unwatchable.

However, there’s an emotional capability that I didn’t remember immediately. I’m speaking, of course, of the Death of Artax. The story-lead Atreyu, leading his horse (Artax) through the Swamps of Sadness, realizes that the sadness has overtaken the poor horse, eventually drowning the beast. Atreyu, obviously, emotionally distraught… cries out for his horse. Sebastian, the “kid reading the story,” cries out for the horse. And Lydia, tears streaming from eyes to ears, gave the most accusatory glares as she could muster for the parents who decided to show her a pony-snuff-film.

I didn’t look at my computer once, hauled 160+ pounds of children and pumpkin around all day (although, a good 10 pounds of weight was likely just in dirt.) All told, not a bad day off.

Fall stuff.

September came and went quickly, and October seems to be doing the same. Work is steady, long and challenging, and in my project, we’re solving some problems that needed to be solved. Given other projects I’ve been on, it’s a nice pace.

On the family front, the fall schedule has come upon us with full force. Every day of the week, there’s something going on, whether it’s preschool during the week, or some such activity planned on the weekend, and up until recently, when some of the kids simply came down with the seasonal whatnots, an unplanned block of 20 minutes rarely seemed to come entirely into fruition.

Notable things that have happened since my last post.
– We went to the fair, in the pouring rain (the pictures are good, but Heather doesn’t like my Picture adder thing on this website.)
– I ate a Maple Bar with Bacon on it at Frost donuts in Mill Creek.
– The kids have started preschool (and almost immediately afterwords)
– The kids have all started coughs/colds/flu stuff.
– Lydia turned 3.
– Zoe has gotten herself almost 100% potty trained.

Final things… we’ve been starting to think about Kindergarten and 1st grade for Zoe. Next year, she’ll start kindergarten.

Beyond that… we’re keepin’ on.

Way to long to post something.

But everything’s broken with the heat… arg!

Just to get back into the swing of posting more regularly, I’m gonna start this one with a link I like. To those who like Obama’s healthcare plan, please read: the following. If you get nothing from it, just remember the following:

As with any good or service that is provided by some specific group of men, if you try to make its possession by all a right, you thereby enslave the providers of the service, wreck the service, and end up depriving the very consumers you are supposed to be helping.

– Dr. Leonard Peikoff

Other notes: we’re all fine. To everyone.. sorry for taking so long. We all say Hi.