【问题标题】:factorial function in the IO monad haskellIO monad haskell 中的阶乘函数
【发布时间】:2015-10-22 01:41:11
【问题描述】:

我在 IO monad haskell 中做阶乘函数。 我按照示例 mod3 使用 IO monad 执行阶乘函数。 我不明白为什么我的代码是错误的。 我想看看n>=1,然后对n做阶乘。 最后添加到 (n,r2) 并返回。 谁能帮忙理解一下?

while :: IO Bool -> IO () -> IO ()
while test body =
  do b <- test
     if b
       then do {body ; while test body}  -- same-line syntax for do
       else return ()

-- remainder when integer-dividing n by 3
mod3 :: Integer -> IO Integer
mod3 n = do r <- newIORef n
            while
              (do {v <- readIORef r; return (v >= 3)})
              (do {v <- readIORef r; writeIORef r (v-3)})
            readIORef r          

-- ghci> fact 4
-- (4,24)
fact :: Integer -> IO (Integer, Integer)
fact n = do r2 <- newIORef n
            while 
            (do {v2 <- readIORef r2; return (v2 >= 1)})
            (do {v2 <- readIORef r2; writeIORef r2 (v2*fact(v2-1))})
            readIORef (n,r2) 

【问题讨论】:

  • 你的代码做什么或不做什么?
  • 你能解释一下你想要完成什么吗?你为什么使用IORefs?
  • 我的代码是计算一个数字的阶乘,例如事实 4,它返回一个列表 (4,24)。 4是给用户的数字,24是4!

标签: haskell io-monad


【解决方案1】:

在这部分代码中:

readIORef (n,r2) 

(n,r2) 不是 IORef。 r2 是一个 IORef,所以你这是合法的:

readIORef r2

那么试试这个怎么样:

  1. 读取 IORef r2 获取值
  2. 返回 (n, ...) 对,其中 ... 是您在步骤 1 中得到的值

【讨论】:

    【解决方案2】:

    首先,将while的参数缩进,否则为新语句。

    fact :: Integer -> IO (Integer, Integer)
    fact n = do r2 <- newIORef n
                while 
                  (do {v2 <- readIORef r2; return (v2 >= 1)})
                  (do {v2 <- readIORef r2; writeIORef r2 (v2*fact(v2-1))})
                readIORef (n,r2) 
    

    其次,while 的样子大致对应于命令式代码:

    while r2 >= 1 :
      r2 = r2 * fact(r2-1)
    

    这毫无意义:为什么要递归调用?您肯定知道如何用传统的命令式语言以命令式风格编写阶乘;从那里开始并将其转换为 Haskell。

    【讨论】:

      【解决方案3】:

      我发现有两个问题阻碍了编译。第一个是fact (v2-1) 的类型为IO (Integer, Integer),但您正试图将其乘以v2 :: Integer。您需要对fact (v2-1) 进行排序,就像对readIORef r2 进行排序一样,乘以该对的第二个分量。

      第二,你误用了readIORef。你可以看到它的签名here。它需要一个IORef a,而不是一对。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-13
        • 2012-06-08
        • 1970-01-01
        相关资源
        最近更新 更多