F#: Market Checkout Kata

Intro

I have been trying to sustain my learning of the F# programming language.
It’s been both stressful and a thrill.

I recently attempted the following kata:

  Item   Unit      Special
         Price     Price
  --------------------------
    A     50       3 for 130
    B     30       2 for 45
    C     20
    D     15

Code

I learned some things as I performed this exercise. For example, I have learned that I could have a function with a descriptive name serve as an alias for another function. I also learned the value of attaching functions to record types.

The following code was generated when I attempted to practice this Kata in F#:

module Checkout

(*Types*)
type Type = A | B | C | D
type Total = { UnitPrice:int ; Qty:int }
             member x.Price() = x.UnitPrice * x.Qty
type Item =
    { Type:Type ; Total:Total

    } member x.SpecialPrice qty qtyPrice =
          if x.Total.Qty / qty > 0
          then (x.Total.Qty / qty) * qtyPrice + (x.Total.Qty % qty) * x.Total.UnitPrice
          else x.Total.Price()

      member x.Price() =
        match x.Type with
        | A -> x.SpecialPrice 3 130
        | B -> x.SpecialPrice 2 45
        | _ -> x.Total.Price()

(*Functions*)
let private getTypeQty = List.sumBy(fun x -> x.Total.Qty)

let private consolidate consolidated (group:Item seq) =

    let qtyOf = List.ofSeq >> getTypeQty
    let first = group |> List.ofSeq |> List.head
    { Type    =  first.Type;
      Total   = { Qty= qtyOf group; UnitPrice= first.Total.UnitPrice }}
                :: consolidated
(*Tests*)
open FsUnit
open NUnit.Framework

[<Test>]
let ``buying (2) A units, (1) B unit, (1) A unit = $160`` () =

    // Setup
    let a2 = { Type=A; Total={UnitPrice=50; Qty=2} }
    let b =  { Type=B; Total={UnitPrice=30; Qty=1} }
    let a =  { Type=A; Total={UnitPrice=50; Qty=1} }

    seq [a2; b; a] |> Seq.groupBy (fun item -> item.Type)
                   |> List.ofSeq
                   |> List.map snd
                   |> List.fold consolidate []
                   |> List.sumBy (fun item -> item.Price())
                   |> should equal 160

Conclusion

This Kata resulted in me learning how to attach functions to records in F#. I think it’s better for a record to have an attached function to process its data than an external function. Hence, I think some things are better coupled.

Advertisements

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: