在静态类型语言干净,类型安全状态机实现? [英] Clean and type-safe state machine implementation in a statically typed language?
问题描述
我实现了一个简单的状态机Python中的:
I implemented a simple state machine in Python:
import time
def a():
print "a()"
return b
def b():
print "b()"
return c
def c():
print "c()"
return a
if __name__ == "__main__":
state = a
while True:
state = state()
time.sleep(1)
我想将它移植到C,因为它不够快。但是C没有让我返回同一类型的函数的函数。我试图使这种类型的功能:的typedef * FN(FN)()
,但它不工作,所以我不得不使用一个结构,而不是。现在,code是非常难看!
I wanted to port it to C, because it wasn't fast enough. But C doesn't let me make a function that returns a function of the same type. I tried making the function of this type: typedef *fn(fn)()
, but it doesn't work, so I had to use a structure instead. Now the code is very ugly!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct fn {
struct fn (*f)(void);
} fn_t;
fn_t a(void);
fn_t b(void);
fn_t c(void);
fn_t a(void)
{
fn_t f = {b};
(void)printf("a()\n");
return f;
}
fn_t b(void)
{
fn_t f = {c};
(void)printf("b()\n");
return f;
}
fn_t c(void)
{
fn_t f = {a};
(void)printf("c()\n");
return f;
}
int main(void)
{
fn_t state = {a};
for(;; (void)sleep(1)) state = state.f();
return EXIT_SUCCESS;
}
所以我想这是用C的破碎式系统出了问题。所以我用一个真正的类型系统(哈斯克尔)的语言,但同样的问题发生。我不能这样做:
So I figured it's a problem with C's broken type system. So I used a language with a real type system (Haskell), but the same problem happens. I can't just do something like:
type Fn = IO Fn
a :: Fn
a = print "a()" >> return b
b :: Fn
b = print "b()" >> return c
c :: Fn
c = print "c()" >> return a
我得到的错误,周期型同义词声明
。
所以,我必须做出一些包装的方式我也为C code这样相同的:
So I have to make some wrapper the same way I did for the C code like this:
import Control.Monad
import System.Posix
data Fn = Fn (IO Fn)
a :: IO Fn
a = print "a()" >> return (Fn b)
b :: IO Fn
b = print "b()" >> return (Fn c)
c :: IO Fn
c = print "c()" >> return (Fn a)
run = foldM (\(Fn f) () -> sleep 1 >> f) (Fn a) (repeat ())
为什么会这样很难做出一个状态机在静态类型语言?我必须作出不必要的开销在静态类型语言。动态类型语言没有这个问题。是否有更简单的方法做,在静态类型语言?
Why is it so hard to make a state machine in a statically typed language? I have to make unnecessary overhead in statically typed languages as well. Dynamically typed languages don't have this problem. Is there an easier way to do it in a statically typed language?
推荐答案
如果您使用 NEWTYPE
而不是数据
,你不承担任何费用。此外,您还可以在定义点包裹每个状态的功能,让使用它们的前pressions不必为:
If you use newtype
instead of data
, you don't incur any overhead. Also, you can wrap each state's function at the point of definition, so the expressions that use them don't have to:
import Control.Monad
newtype State = State { runState :: IO State }
a :: State
a = State $ print "a()" >> return b
b :: State
b = State $ print "b()" >> return c
c :: State
c = State $ print "c()" >> return a
runMachine :: State -> IO ()
runMachine s = runMachine =<< runState s
main = runMachine a
修改:这让我吃惊 runMachine
有一个更一般的形式; 迭代
的一元版本:
Edit: it struck me that runMachine
has a more general form; a monadic version of iterate
:
iterateM :: Monad m => (a -> m a) -> a -> m [a]
iterateM f a = do { b <- f a
; as <- iterateM f b
; return (a:as)
}
main = iterateM runState a
修改:嗯, iterateM
将导致空间泄漏。也许 iterateM _
效果会更好。
Edit: Hmm, iterateM
causes a space-leak. Maybe iterateM_
would be better.
iterateM_ :: Monad m => (a -> m a) -> a -> m ()
iterateM_ f a = f a >>= iterateM_ f
main = iterateM_ runState a
修改:如果您想通过状态机线程的一些状态,您可以使用国家
的定义相同,但改变国家功能:
Edit: If you want to thread some state through the state machine, you can use the same definition for State
, but change the state functions to:
a :: Int -> State
a i = State $ do{ print $ "a(" ++ show i ++ ")"
; return $ b (i+1)
}
b :: Int -> State
b i = State $ do{ print $ "b(" ++ show i ++ ")"
; return $ c (i+1)
}
c :: Int -> State
c i = State $ do{ print $ "c(" ++ show i ++ ")"
; return $ a (i+1)
}
main = iterateM_ runState $ a 1
这篇关于在静态类型语言干净,类型安全状态机实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!