【问题标题】:How to get a working state machine in F# using functions for representing states?如何使用表示状态的函数在 F# 中获取工作状态机?
【发布时间】:2014-10-25 09:29:54
【问题描述】:

我正在尝试在 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”时,会抛出空引用异常。
无论如何,选择的方法是否可以解决这个问题,或者我应该以不同的方式对其进行建模?

【问题讨论】:

  • 您的示例未编译 - 它给了我关于“和 pingState”的值限制错误
  • 这很奇怪;我在 fsx 文件中得到相同的编译错误,但在 fs 文件中没有(在上面的示例中添加了程序代码)

标签: recursion f# state-machine mutual-recursion


【解决方案1】:

这就是我所做的:

#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 导致的状态上的多余类型注释抱怨他们被推断为通用的。很多投诉;)

至于不同的建模 - 我想我会将它包装在一个类型中而不是单独使用函数,这似乎更自然。我想使用函数是这里的重点。

【讨论】:

  • 谢谢!在 fs 文件中,上面也可以在没有明确指定 pongState 和 pingState 的返回类型的情况下工作,不知道为什么它在 fs 和 fsx 之间有所不同,
  • 在 fs 文件中有足够的上下文来推断这些状态的具体类型。当您在 fsi 中尝试某些东西时,情况通常并非如此。如果您稍后在 fsx 中定义了一个使用这些状态的函数,以便可以从中推断出类型,您也可以删除 fsx 中的注释。
  • 我明白了,但是关于 fsi 案例中缺少的类型推断, fs 上下文中有什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 1970-01-01
  • 1970-01-01
  • 2022-10-08
相关资源
最近更新 更多