简体   繁体   中英

Translate C code into Haskell

How do I translate this portion of C code into Haskell? From what I know, I must use the State monad, but I don't know how.

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

Let's assume, you have that pair of integers as state:

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

Is that, what you want?

A literal translation would use 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)

As you can see, imperative programming is ugly in Haskell. This is intentional, to coax you into using functional style. You can define some helper functions, though, to make this more bearable:

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

The point of functional languages for you to not do that, make a new value, or use recursion.

If you like to just print these values,

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

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

If this is a homework assignment, please mark it as so, and I will change my answer.

another way is to think about "versions" of the variable - the x at the start is different than the x at the end. For example, in C say you have a variable that sometimes stores a number in fahrenheit and then you convert it to centigrade, like this:

  temp = 40;
  temp = convertFtoC(temp);

then you could think about these as two different variables:

   tempF = 40;
   tempC=  convertFtoC(tempF);

Without knowing what your x and y are to invent better names for them, you might end up writing in haskell:

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

In some cases, that can be a nice way to think about how to make your code more functional and less imperative.

If you identify your "mutable" variables with a tuple, you can define transformation operations on it and "chain" it together:

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... sets a value, app... applies a function on it, app2... applies a function on both values and stores it in x or y. Then you can do something like:

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

Your example would become:

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

Of course this stretches the definition of "mutable" a bit, but this solution is already half way to the State or Writer monad.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM