(Again, standard disclaimers apply, use at your own risk, etc.)
type Query =
| Yes
| No
| Unknown
let Conjoin q0 q1 =
match q0 with
| Query.No -> Query.No
| Query.Yes -> q1
| _ -> match q1 with
| Query.No -> Query.No
| _ -> Query.Unknown
let Disjoin q0 q1 =
match q0 with
| Query.Yes -> Query.Yes
| Query.No -> q1
| _ -> match q1 with
| Query.Yes -> Query.Yes
| _ -> Query.Unknown
let Negate q0 =
match q0 with
| Query.Yes -> Query.No
| Query.No -> Query.Yes
| _ -> q0
let rec Junction (fc:Query->Query->Query)
(ft:Query->bool)
(lq:Lazy<Query> list) =
match lq with
| [] -> Query.Unknown
| h::[] -> h.Value
| h::t ->
match ft h.Value with
| true -> h.Value
| _ -> fc h.Value
(Junction fc ft t)
let rec Conjunction (lq:Lazy<Query> list) =
Junction Conjoin (fun h->h=Query.No) lq
let rec Disjunction (lq:Lazy<Query> list) =
Junction Disjoin (fun h->h=Query.Yes) lq
let rec All (lq:Lazy<Query> list) =
Junction Disjoin (fun h->false) lq
let rec Not (lq:Lazy<Query>) = lazy (
Negate lq.Value)
let rec internal GetQuery q =
printf "%s (y/n/u) " q
let key = Console.ReadKey().KeyChar
printfn ""
match key with
| 'y' | 'Y' -> Query.Yes
| 'n' | 'N' -> Query.No
| 'u' | 'U' -> Query.Unknown
| _ -> GetQuery q
let black = lazy ( GetQuery "Is it black?" )
let orangeColor = lazy ( GetQuery "Is it orange?" )
let white = lazy ( GetQuery "Is it white?" )
let orange = lazy (
Disjunction [
orangeColor;
lazy ( GetQuery "Is it an orange?" )])
let blackAndWhite = lazy (
Conjunction [
black;
white])
let blackAndOrange = lazy (
Conjunction [
black;
orange])
let blackAndWhiteAndOrange = lazy (
Conjunction [
black;
white;
orange])
let blackAndWhiteOnly = lazy (
Conjunction [
blackAndWhite;
(Not orange)])
let blackAndOrangeOnly = lazy (
Conjunction [
blackAndOrange;
(Not white)])
let color = lazy (
All [
blackAndWhite;
blackAndOrange;
blackAndWhiteAndOrange;
blackAndWhiteOnly;
blackAndOrangeOnly])
color.Value |> ignore
No comments:
Post a Comment