将 C 代码翻译成 Haskell

发布于 2024-11-10 10:41:16 字数 135 浏览 2 评论 0原文

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

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

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

临风闻羌笛 2024-11-17 10:41:16

假设您有这对整数作为状态:

f = do put (1,2)
       modify (\(x,y) -> (x*y,y))
       modify (\(x,y) -> (x,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?

空‖城人不在 2024-11-17 10:41:16

直译将使用 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

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
冬天旳寂寞 2024-11-17 10:41:16

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

如果您只想打印这些值,

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

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

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

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.

甜心 2024-11-17 10:41:16

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

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

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.

吃不饱 2024-11-17 10:41:16

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

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... code> 对它应用一个函数,app2... 对两个值应用一个函数并将其存储在 x 或 y 中。然后你可以这样做:

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

你的例子将变成:

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

当然,这稍微扩展了“可变”的定义,但这个解决方案已经是 StateWriter 单子。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文