将C代码转换为Haskell

如何将这部分C代码翻译成Haskell? 据我所知,我必须使用State monad,但我不知道如何。

int x = 1; int y = 2; x = x * y; y = y + x; 

字面翻译将使用IORefs :

 import Data.IORef main :: IO () main = do x <- newIORef 1 y <- newIORef 2 y_val <- readIORef y modifyIORef x (\v -> v * y_val) x_val <- readIORef x modifyIORef y (\v -> v + x_val) 

正如您所看到的,命令式编程在Haskell中很难看。 这是故意的,诱使你使用function风格。 但是,您可以定义一些辅助函数,以使其更具可接受性:

 import Data.IORef -- x := fxy combineToR :: (a -> t -> a) -> IORef a -> IORef t -> IO () combineToR fxy = do y_val <- readIORef y modifyIORef x (\v -> fv y_val) addTo :: Num a => IORef a -> IORef a -> IO () addTo = combineToR (+) multWith :: Num a => IORef a -> IORef a -> IO () multWith = combineToR (*) main :: IO () main = do x <- newIORef 1 y <- newIORef 2 multWith xy addTo yx 

让我们假设,你有一对整数作为状态:

 f = do put (1,2) modify (\(x,y) -> (x*y,y)) modify (\(x,y) -> (x,y+x)) 

那是你要的吗?

函数式语言要点不要这样做,创建新值或使用递归。

如果您只想打印这些值,

 x = 1 y = 2 a = x*y b = y+x main = do putStrLn ("x*y: " ++ a) putStrLn ("y+x: " ++ b) 

如果这是家庭作业,请将其标记为,我将更改我的答案。

另一种方法是考虑变量的“版本” – 开头的x与末尾的x不同。 例如,在C中说你有一个变量,有时会以华氏温度存储一个数字,然后你将其转换为摄氏度,如下所示:

   temp = 40;
   temp = convertFtoC(temp);

那么你可以把它们看作两个不同的变量:

    tempF = 40;
    tempC = convertFtoC(tempF);

如果不知道你的x和y为他们创造了更好的名字,你最终可能会写入haskell:

 xa = 1;
 ya = 2;
 xb = xa * ya;
 yb = ya + xb;

在某些情况下,这可能是思考如何使代码更具function性和更少命令性的好方法。

如果使用元组标识“可变”变量,则可以在其上定义转换操作并将其“链接”在一起:

 vars xy = (x,y) setX (x,y) x' = (x', y) setY (x,y) y' = (x, y') appX (x,y) f = (fx, y) appY (x,y) f = (x, fy) app2X (x, y) f = (fxy, y) app2Y (x, y) f = (x, fxy) 

set...设置一个值, app...对它应用一个函数, app2...在两个值上应用一个函数并将其存储在x或y中。 然后你可以这样做:

 (vars 3 5) `setX` 14 `appY` (2*) -- result: (14,10) 

你的例子将成为:

 (vars 1 2) `app2X` (*) `app2Y` (+) -- result: (2,4) 

当然,这延伸了“可变”的定义,但是这个解决方案已经到了StateWriter monad的一半。