anchor.diff:  
       let rec classifyInt (node:TreeNode<'T, 'U>) =
           match node with
  -        | Category(categorySelector) -> categorySelector datum
  +        | Category(category) -> category
           | Node(selector, nodes) -> match chooseNode selector nodes with
                                      | Some(node) -> classifyInt node
                                      | None -> failwith "no node"
   
  -    let value = classifyInt tree
  +    let root = match tree with |Root(r) -> r
  +    let value = classifyInt root
       value
   
  -//let trainID3 (data: 'T seq) (categorySelector:'T -> 'U) (features: seq<'T -> obj>) = 
  +let trainID3 (data: 'T seq) (categorySelector:'T -> 'U) (features: seq<'T -> obj>) = 
       
  +    let rec trainID3Int restData (featureSelector:'T -> obj) (currentNode:TreeNode<'T, 'U>) (otherFeatures: ('T -> obj) list) =
  +        let restDataCount = restData |> Seq.length |> float
  +        let getDataDistribution featureData =
  +            let featDataByCatProb = featureData 
  +                                    |> Seq.groupBy categorySelector
  +                                    |> Seq.map (fun (cat, d) -> cat, (d |> Seq.length |> float) / restDataCount)
  +            featDataByCatProb
  +        
  +        match otherFeatures with
  +        | [] -> let partData = restData 
  +                                    |> Seq.groupBy featureSelector
  +                                    |> Seq.map (fun (feature, featData) -> feature, getDataDistribution featData) 
  +                                    |> Seq.map (fun (feature, featDataByCatProb) -> feature, featDataByCatProb |> Seq.maxBy snd |> fst ) // can keep the probability
  +                                    |> Seq.map (fun (feature, cat) -> feature, Category(cat)) |> Seq.toList
  +                Node(featureSelector, partData)
  +    ()
   
  +               
  +type Mov = {Action:bool; SciFi:bool; Actor:string}
  +
  +let catSelector = fun (m:Mov) -> m.Actor
  +let actionSelector = fun (m:Mov) -> m.Action :> obj
  +let sciFiSelector = fun (m:Mov) -> m.SciFi :> obj
  +
  +let root = Node(
  +                sciFiSelector, [
  +                        (true :> obj, Category("A"))
  +                        (false:> obj, Node(actionSelector, [
  +                                            (true :> obj, Category("S"));
  +                                            (false:> obj, Category("A"))
  +                        ]
  +                        ))
  +                ])
  +let tree = Root(root)
  +
  +let t1 = {Action=true;  SciFi=true;  Actor=""}
  +let t2 = {Action=true;  SciFi=false; Actor=""}
  +let t3 = {Action=false; SciFi=true;  Actor=""}
  +let t4 = {Action=false; SciFi=false; Actor=""}
  +
  +
  
positive.code: ﻿module DecisionTrees﻿
  // https://en.wikipedia.org/wiki/ID3_algorithm
  // http://stackoverflow.com/questions/1418829/help-needed-creating-a-binary-tree-given-truth-table
  // https://blogs.msdn.microsoft.com/chrsmith/2009/10/31/awesome-f-decision-trees-part-i/
  
  let private entropyInternal (categorySelector:'T -> 'U) (data:'T seq) =
      let log2 x = System.Math.Log(x, 2.0)
  
negative.code:     dataEntr-partDataEntr
  
  type TreeNode<'T, 'U> = 
          |Category of 'U
          |Node of ('T -> obj) * (obj * TreeNode<'T, 'U>) list
  
  type Tree<'T, 'U> = |Root of TreeNode<'T, 'U>
  
  let classify (datum:'T) (tree:Tree<'T, 'U>) = 
      let rec chooseNode (selector:('T -> obj)) (nodes:( obj * TreeNode<'T, 'U>) list) =
  