将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)
当然,这延伸了“可变”的定义,但是这个解决方案已经到了State
或Writer
monad的一半。