Standard disclaimers and caveats apply: a weekend fun project, not thoroughly tested, use at your own risk.
open System
// See previous post for additional comments.
// Formatted for blog width.
// Certainty factors based on categories.
type Certainty =
| Impossible = 0
| Disproven = 1
| Unlikely = 2
| Possible = 3
| Likely = 4
| Proven = 5
| Certain = 6
// Likely and Unlikely define the boundaries for
// acceptance and rejection.
let Likely (c) = c>=Certainty.Likely
let Unlikely (c) = c<=Certainty.Unlikely
// Custom Min and Max.
let Min c0 c1 =
match (c0<c1) with
| true -> c0
| false -> c1
let Max c0 c1 =
match (c0>c1) with
| true -> c0
| false -> c1
// I cleaned up the Consider functions quite a bit.
let ConsiderBase s (b:Lazy<Certainty>) =
printfn "Considering <-- %s" s
printfn "Concluding --> %s is %s" s (b.Value.ToString())
let Consider s (b:Lazy<Certainty>) = lazy (
ConsiderBase s b
b.Value)
let ConsiderImmediate s (b:Lazy<Certainty>) =
ConsiderBase s b
b
// Conjunction functions converted to certainty.
let Conjoin a (b:unit->Certainty) =
match Unlikely(a) with
| true -> a
| false -> Min a (b())
let rec ConjunctionPossible (l:Lazy<Certainty> list) =
match l with
| [] -> Certainty.Certain
| h::t ->
match h.IsValueCreated with
| false -> ConjunctionPossible(t)
| true ->
Conjoin
h.Value
(fun unit -> ConjunctionPossible(t))
let rec ConjunctionEval (l:Lazy<Certainty> list) =
match l with
| [] -> Certainty.Certain
| h::t ->
Conjoin
h.Value
(fun unit -> ConjunctionEval(t))
let Conjunction (l:Lazy<Certainty> list) = lazy (
let possible = ConjunctionPossible(l)
match Unlikely(possible) with
| true -> possible
| false -> ConjunctionEval(l))
// Disjunction functions converted to certainty.
let Disjoin a (b:unit->Certainty) =
match Likely(a) with
| true -> a
| false -> Max a (b())
let rec DisjunctionPossible (l:Lazy<Certainty> list) =
match l with
| [] -> Certainty.Impossible
| h::t ->
match h.IsValueCreated with
| false -> Certainty.Certain
| true ->
Disjoin
h.Value
(fun unit -> DisjunctionPossible(t))
let rec DisjunctionEval (l:Lazy<Certainty> list) =
match l with
| [] -> Certainty.Impossible
| h::t ->
Disjoin
(h.Value)
(fun unit -> DisjunctionEval(t))
let Disjunction (l:Lazy<Certainty> list) = lazy (
let possible = DisjunctionPossible(l)
match Unlikely(possible) with
| true -> possible
| false -> DisjunctionEval(l))
// This function will evaluate all hypotheses.
let rec Maximum (l:Lazy<Certainty> list) = lazy (
match l with
| [] -> Certainty.Impossible
| h::t -> Max h.Value (Maximum(t)).Value)
// Sample data.
let black =
Consider "black" (lazy Certainty.Possible)
let blue =
ConsiderImmediate "blue" (lazy Certainty.Likely)
let orange =
Consider "orange" (lazy Certainty.Unlikely)
let white =
Consider "white" (lazy Certainty.Likely)
let blackAndOrange =
Consider
"blackAndOrange"
(Conjunction [
black;
orange ])
let blackAndOrangeOrBlue =
Consider
"blackAndOrangeOrBlue"
(Disjunction [
blackAndOrange;
blue ])
let whiteAndBlack =
Consider
"whiteAndBlack"
(Conjunction [
white;
black ])
let color =
ConsiderImmediate
"colorIsKnown"
(Disjunction [
blackAndOrange;
blackAndOrangeOrBlue;
whiteAndBlack ])
Console.ReadLine() |> ignore