recursion - 如何使用表示状态的函数在 F# 中获得工作状态机?

标签 recursion f# state-machine mutual-recursion

我正在尝试在 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()输入“go to pong”,状态切换到pong。但是当调用输入“go to 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 提示它们被推断为通用。很多投诉;)

至于以不同的方式对其进行建模 - 我认为我会将它包装在一种类型中,而不是仅使用函数,这似乎更自然。我想使用函数是这里的重点。

关于recursion - 如何使用表示状态的函数在 F# 中获得工作状态机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26561012/

相关文章:

algorithm - 计算递归函数的大O

Python递归函数从字典中获取数据

C:寻找树中特定叶子的霍夫曼编码路径

c# - 在(通过转换为状态机)递归生成器方法中摆脱 'yield' 的最简单方法?

java - Spring 状态机的替代品

python - C++ 中的递归生成器

.net - String 和 Stream 的 .NET MD5 Hash 之间的区别

inheritance - F# 将额外的情况添加到外部 DU

f# - 如何在计算表达式中定义自定义运算符

python - 是否有可以对有限状态机进行时间逻辑模型检查的 Python 包?