如何在F#中使用表示状态的函数来获得一个工作状态机



我试图在F#中创建一个简单的状态机,但在获得两个具有循环依赖关系的状态时遇到了问题
我有一家国营工厂:

open System
let createState produceInput stateSwitchRule nextState = 
    let rec stateFunc() = 
        match produceInput() with
        | x when x = stateSwitchRule -> printfn "%s" "Switching state"; nextState()
        | _  -> printfn "%s" "Bad input. Try again"; stateFunc()
    stateFunc

我用它来创建两个相互递归的状态:

let rec pongState() = createState Console.ReadLine "go to ping" pingState
      and pingState = createState Console.ReadLine "go to pong" (pongState())
[<EntryPoint>]
let main argv = 
    pingState()
    0

当调用pingState()并输入"转到pong"时,状态切换到pong。但是当调用输入"转到ping"时,会抛出一个空引用异常
选择的方法是否存在这种情况,或者我应该以不同的方式进行建模?

这就是我所做的:

#nowarn "40"
open System
let createState produceInput stateSwitchRule nextState = 
    let rec stateFunc () = 
        match produceInput() with
        | x when x = stateSwitchRule -> printfn "%s" "Switching state"; (nextState()) ()
        | _  -> printfn "%s" "Bad input. Try again"; stateFunc()
    stateFunc
let rec pongState : unit -> (unit -> string) = createState Console.ReadLine "go to ping" (fun () -> pingState)
    and pingState : unit -> (unit -> string) = createState Console.ReadLine "go to pong" (fun () -> pongState)

#nowarn "40",以抑制有关检查递归定义对象的初始化可靠性、nextState函数的不同类型的警告,否则编译器抱怨某个值作为其定义的一部分进行评估,以及对状态的多余类型注释,因为FSI抱怨它们被推断为泛型。很多抱怨;)

至于以不同的方式建模——我想我会把它封装在一个类型中,而不是只使用函数,这似乎更自然。不过,我想使用函数才是重点。

最新更新