将C代码转换为Haskell

时间:2011-05-31 19:09:03

标签: c haskell translate

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

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

5 个答案:

答案 0 :(得分:9)

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

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

那就是你想要的吗?

答案 1 :(得分:8)

字面翻译将使用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中很难看。这是故意的,诱使你使用功能风格。但是,您可以定义一些辅助函数,以使其更具可忍性:

import Data.IORef

-- x := f x y
combineToR :: (a -> t -> a) -> IORef a -> IORef t -> IO ()
combineToR f x y = do y_val <- readIORef y
                      modifyIORef x (\v -> f v 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 x y
          addTo y x

答案 2 :(得分:6)

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

如果您只想打印这些值,

x = 1
y = 2
a = x*y
b = y+x

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

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

答案 3 :(得分:2)

另一种方法是考虑变量的“版本” - 开头的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;

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

答案 4 :(得分:1)

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

vars x y = (x,y)
setX (x,y) x' = (x', y) 
setY (x,y) y' = (x, y') 
appX (x,y) f = (f x, y)
appY (x,y) f = (x, f y)
app2X (x, y) f = (f x y, y)
app2Y (x, y) f = (x, f x y)

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的一半。