2014-10-25 6 views
4

Я пытаюсь создать простой конечный автомат в 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() При вызове и ввод «идти в теннис» состояние переключается в теннис. Но при вызове ввода «go to ping» генерируется исключение нулевой ссылки.
Есть ли все-таки вокруг этого с выбранным подходом или я должен моделировать его по-другому?

+0

Ваш образец не компилируется - он дает мне ошибку ограничения значения на 'и pingState' – Petr

+0

Это странно; Я получаю ту же ошибку компиляции в файле fsx, но не в файле fs (добавлен код программы к приведенному выше примеру) – Christian

ответ

3

Это то, что я сделал:

#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 жаловался на то, что они считаются родовыми. Множество жалоб;)

Что касается моделирования по-разному - я думаю, что я бы обернул его типом вместо использования исключительно функций, это кажется более естественным. Я предполагаю, что использование функций было здесь всецело.

+0

Спасибо! В файле fs вышеупомянутое также работает без явного указания возвращаемых типов pongState и pingState, не знаю, почему оно отличается между fs и fsx, – Christian

+0

В файле fs достаточно контекста для вывода конкретных типов этих состояний. Это часто бывает не так, когда вы тестируете материал в fsi. Если у вас была функция, определенная позже в fsx, которая использует эти состояния, чтобы типы могли быть выведены из нее, вы могли бы также удалить аннотации в fsx. – scrwtp

+0

Я вижу, но что в fs-контексте относительно вывода типа, отсутствующего в fsi-case? – Christian

 Смежные вопросы

  • Нет связанных вопросов^_^