Business Logic and F#

One of the reasons I like F# so much is that it allows me to think about the problem I am trying to solve, not about the language syntax and coding around language constructs.  Consider this example. 

I am putting on an art show in my neighborhood and I managed to obtain 3 paintings of cultural significance:

Starry Night

Capture2

Sunday Afternoon on the Island of La Grande Jatte

Capture

Dogs Playing Poker

Capture3

Each painting is in its own room and due to the volume of people that the art gallery can support, a person can only visit 1 painting.  1,000 tickets sold and all 1,000 people are going to show up.  This is a hot event.

I needed a way to forecast how many people will go into each room.  Since all 3 paintings are immensely popular, I could assume that each room will have 1/3 the number of visitors.  However, I wanted to be be a bit more precise and I know that each painting has a certain number of tags associated with them:

Tag Starry Night Afternoon Poker
Impressionism X X  
Nature X X  
Leisure Activity   X X
Modernism     X

Assuming that people will want to go see paintings with tags that interest them, paintings that have tag overlap will split visitors, paintings with no tag overlap will see more visitors, and paintings with more tags will draw more visitors.  In Excel:

Tag Starry Night Afternoon Poker Total
Impressionism 1 1   2
Nature 1 1   2
Leisure Activity   1 1 2
Modernism     1 1
         
         
Tag Starry Night Afternoon Poker  
Impressionism 0.5 0.5    
Nature 0.5 0.5    
Leisure Activity   0.5 0.5  
Modernism     1  
         
         
Tag People Starry Night Afternoon Poker
Impressionism 250 125 125  
Nature 250 125 125  
Leisure Activity 250   125 125
Modernism 250     250
  1,000 250 375 375

Putting this to code, I opened up the F# REPL and created my art show like so:

1 2 type Painting = {id:int;name:string;tags:string} 3 type ArtShow = {id:int;name:string;expectedAttendance:int;paintings:Painting list} 4 5 let painting0 = {id=0; 6 name="Starry Night"; 7 tags="Impressionism;Nature"} 8 let painting1 = {id=1; 9 name="Sunday Afternoon on the Island of La Grande Jatte"; 10 tags="Impressionism;Nature;LeisureActivities"} 11 let painting2 = {id=2; 12 name="Dogs Playing Poker"; 13 tags="Modernism;LeisureActivities"} 14 let paintings = [painting0;painting1;painting2] 15 16 let artShow = {id=0; 17 name="Art Extravaganza"; 18 expectedAttendance=1000; 19 paintings=paintings} 20

I then needed a way of uniquely identifying the tags.  Enter the goodness of piping and high order functions:

1 let tagSet = artShow.paintings |> Seq.map(fun p -> p.tags) 2 |> Seq.collect(fun t -> t.Split(';')) 3 |> Seq.groupBy(fun t -> t) 4 |> Seq.map(fun (id,t) -> id, t |> Seq.length) 5

image

I then needed a way of assigning number of people to tags.  Easy enough (this could have been part of the code block above but I split it for illustrative purposes)

1 let visitorsPerTag = artShow.expectedAttendance / (tagSet |> Seq.length) 2 let tagSet' = tagSet |> Seq.map(fun (id,c) -> id, visitorsPerTag/ c )

image

And then a function that calculates the number of expected visitor based on that the individual painting:

1 let tagModifier(painting: Painting) = 2 let tags = painting.tags.Split(';') 3 tags |> Seq.map(fun pt -> tagSet' |> Seq.find(fun(t,c) -> pt = t)) 4 |> Seq.sumBy(fun(t,c) -> c )

And running it against my show’s paintings gives me the expected values:

1 artShow.paintings |> Seq.map(fun p -> p, tagModifier(p)) 2

image

So this is why I love F#.  The REPL and the language helped me reason and solve the problem.  You can see the gist here.

After note: I sent the same challenge to some C# devs I know about how they would reason and then code the answer.  No one took me up on it.

Advertisements

One Response to Business Logic and F#

  1. Pingback: F# Weekly #22, 2015 | Sergey Tihon's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: