下面的代码来自https://www.manning.com/books/real-world-function-programming的第8章
当我运行代码时,我在 testClientTree 中收到空引用异常。我检查了这本书的勘误表,但没有找到任何与此相关的内容。
type Client =
{ Name : string
Income : int
YearsInJob : int
UsesCreditCard : bool
CriminalRecord : bool }
let john =
{ Name = "John Doe"
Income = 40000
YearsInJob = 1
UsesCreditCard = true
CriminalRecord = false }
type ClientTests =
{ Check : Client -> bool
Report : Client -> unit }
type QueryInfo =
{ Title : string
Test : Client -> bool
Positive : Decision
Negative : Decision }
and Decision =
| Result of string
| Query of QueryInfo
let rec tree =
Query({ Title = "More than $40k"
Test = (fun cl -> cl.Income > 40000)
Positive = moreThan40; Negative = lessThan40 })
and moreThan40 =
Query({ Title = "Has criminal record"
Test = (fun cl -> cl.CriminalRecord)
Positive = Result("NO"); Negative = Result("YES") })
and lessThan40 =
Query({ Title = "Years in job"
Test = (fun cl -> cl.YearsInJob > 1)
Positive = Result("YES"); Negative = usesCredit })
and usesCredit =
Query({ Title = "Uses credit card"
Test = (fun cl -> cl.UsesCreditCard)
Positive = Result("YES"); Negative = Result("NO") })
let rec testClientTree(client, tree) =
match tree with
| Result(msg) ->
printfn " OFFER A LOAN: %s" msg
| Query(qi) ->
let s, case = if (qi.Test(client)) then "yes", qi.Positive
else "no", qi.Negative
printfn " - %s? %s" qi.Title s
testClientTree(client, case)
[<EntryPoint>]
let main argv =
testClientTree(john, tree)
0
Run Code Online (Sandbox Code Playgroud)
我不知道为什么书上有这个初始化代码,但是失败的原因是因为数据实际上没有初始化。
你需要这样做:
let rec tree =
Query({ Title = "More than $40k"
Test = (fun cl -> cl.Income > 40000)
Positive =
Query({ Title = "Has criminal record"
Test = (fun cl -> cl.CriminalRecord)
Positive = Result("NO")
Negative = Result("YES") })
Negative =
Query({ Title = "Years in job"
Test = (fun cl -> cl.YearsInJob > 1)
Positive = Result("YES");
Negative =
Query({ Title = "Uses credit card"
Test = (fun cl -> cl.UsesCreditCard)
Positive = Result("YES"); Negative = Result("NO") })})})
Run Code Online (Sandbox Code Playgroud)
正是由于这样的原因,如果可以的话,最好不要定义一堆相互递归的东西。