3 people like it.

Finalizing Tesco purchase

The sample shows two different reprezentations of Tesco checkout. The first one stores scanned items - as a list of either purchase or cancel items - and the second stores final bill with product and total quantity. The snippet implements transformation that corresponds to finalizing the purchase.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
open System
open TescoApi.Tesco

// ------------------------------------------------------------------

type Code = string
type Name = string
type Price = decimal
type Picture = string
type Product = Product of Code * Name * Picture * Price
type Quantity = decimal

type LineItem = 
  | SaleLineItem of int * Product * Quantity
  | CancelLineItem of int

type LinePurchase = list<LineItem>
type FinalPurchase = Map<Product, Quantity>

// ------------------------------------------------------------------

let calculateFinal (line:LinePurchase) : FinalPurchase =
  line
  |> Seq.choose (fun item ->
      match item with
      | SaleLineItem(id, prod, q) -> 
          let cancelled =
            line |> Seq.exists (fun item ->
              match item with
              | CancelLineItem cancelId when cancelId = id -> true
              | _ -> false)
          if cancelled then None
          else Some (prod, q)
      | _ -> None )
  |> Seq.groupBy (fun (prod, q) -> prod)
  |> Seq.map (fun (prod, items) -> 
        prod, Seq.sumBy snd items)
  |> Map.ofSeq
namespace System
type Code = string

Full name: Script.Code
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
type Name = string

Full name: Script.Name
type Price = decimal

Full name: Script.Price
Multiple items
val decimal : value:'T -> decimal (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.decimal

--------------------
type decimal = Decimal

Full name: Microsoft.FSharp.Core.decimal

--------------------
type decimal<'Measure> = decimal

Full name: Microsoft.FSharp.Core.decimal<_>
type Picture = string

Full name: Script.Picture
Multiple items
union case Product.Product: Code * Name * Picture * Price -> Product

--------------------
type Product = | Product of Code * Name * Picture * Price

Full name: Script.Product
type Quantity = decimal

Full name: Script.Quantity
type LineItem =
  | SaleLineItem of int * Product * Quantity
  | CancelLineItem of int

Full name: Script.LineItem
union case LineItem.SaleLineItem: int * Product * Quantity -> LineItem
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
union case LineItem.CancelLineItem: int -> LineItem
type LinePurchase = LineItem list

Full name: Script.LinePurchase
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
type FinalPurchase = Map<Product,Quantity>

Full name: Script.FinalPurchase
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
  interface IEnumerable
  interface IComparable
  interface IEnumerable<KeyValuePair<'Key,'Value>>
  interface ICollection<KeyValuePair<'Key,'Value>>
  interface IDictionary<'Key,'Value>
  new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
  member Add : key:'Key * value:'Value -> Map<'Key,'Value>
  member ContainsKey : key:'Key -> bool
  override Equals : obj -> bool
  member Remove : key:'Key -> Map<'Key,'Value>
  ...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val calculateFinal : line:LinePurchase -> FinalPurchase

Full name: Script.calculateFinal
val line : LinePurchase
module Seq

from Microsoft.FSharp.Collections
val choose : chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.choose
val item : LineItem
val id : int
val prod : Product
val q : Quantity
val cancelled : bool
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.exists
val cancelId : int
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val groupBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'Key * seq<'T>> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.groupBy
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val items : seq<Product * Quantity>
val sumBy : projection:('T -> 'U) -> source:seq<'T> -> 'U (requires member ( + ) and member get_Zero)

Full name: Microsoft.FSharp.Collections.Seq.sumBy
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val ofSeq : elements:seq<'Key * 'T> -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.ofSeq
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/bA
Posted:12 years ago
Author:Tomas Petricek
Tags: tesco , domain modelling , dsl , discriminated union , transformation