Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decision tree (recursive type)

Tags:

f#

I'm stuck with one of the examples from "Real World Functional Progamming", chapter 8 -- decision trees. If I run this code in FSI (version 4.1)

type QueryInfo = {
  Title: string
  Positive: Decision
  Negative: Decision
}
and Decision =
  | Result of string
  | Query of QueryInfo

let rec tree = 
    Query({ Title = "A"
            Positive = aleft; Negative = aright })
and aleft = 
    Query({ Title = "B"
            Positive = bleft; Negative = Result("Yes") })
and aright =
    Query({ Title = "C"
            Positive = Result("No"); Negative = Result("Yes") })
and bleft =
    Query({ Title = "D"
            Positive = Result("No"); Negative = Result("Yes") })

printfn "%A" tree

the value tree is

val tree : Decision = Query {Title = "A";
                            Positive = null;
                            Negative = null;}
val aleft : Decision = Query {Title = "B";
                              Positive = null;
                              Negative = Result "Yes";}
val aright : Decision = Query {Title = "C";
                              Positive = Result "No";
                              Negative = Result "Yes";}
val bleft : Decision = Query {Title = "D";
                              Positive = Result "No";
                              Negative = Result "Yes";}

the values for Positive and Negative for the first two nodes are null, instead of references declared below (aleft, aright, bleft). Hence a function to parse the tree would fail.

How should I define the (recursive) type of a decision tree, in order to obtain a tree structure value?

val tree : Decision = Query {Title = "A";
                            Positive = aleft;
                            Negative = aright;}
val aleft : Decision = Query {Title = "B";
                              Positive = bleft;
                              Negative = Result "Yes";}
...
like image 488
Leo Nistor Avatar asked Jan 29 '26 00:01

Leo Nistor


2 Answers

If I understand correctly it doesn't look like you need a recursive value here. You should be able to just define the entire tree at once:

let tree = 
  Query { Title = "A"
          Positive = Query { Title = "B"
                             Positive = Query { Title = "D"
                                                Positive = Result("No")
                                                Negative = Result("Yes") }
                             Negative = Result "Yes" }
          Negative = Query { Title = "C"
                             Positive = Result "No"
                             Negative = Result "Yes" } }

Printing tree yields this output:

Query {Title = "A";
       Positive = Query {Title = "B";
                         Positive = Query {Title = "D";
                                           Positive = Result "No";
                                           Negative = Result "Yes";};
                         Negative = Result "Yes";};
       Negative = Query {Title = "C";
                         Positive = Result "No";
                         Negative = Result "Yes";};}
like image 51
Taylor Wood Avatar answered Jan 30 '26 14:01

Taylor Wood


This looks very much like a compiler bug.

Here's a shorter repro:

type A = A of B
and B = B of A | C

let rec a = B (A b)
and b = B (A c)
and c = C

Initialization here fails in the same way: a = B (A null).

Filed here, let's see what response I get.

like image 24
Fyodor Soikin Avatar answered Jan 30 '26 15:01

Fyodor Soikin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!