简体   繁体   English

IO monad haskell 中的阶乘函数

[英]factorial function in the IO monad haskell

I am doing the factorial function in the IO monad haskell.我正在 IO monad haskell 中执行阶乘函数。 I followed the example mod3 in order to do the factorial function with IO monad.我遵循示例 mod3 以使用 IO monad 执行阶乘函数。 I cant understand why my code is wrong.我不明白为什么我的代码是错误的。 I want to see if n>=1, and then do the factorial to n.我想看看n>=1,然后对n做阶乘。 Lastly adding to the (n,r2) and return.最后添加到 (n,r2) 并返回。 Can anyone help understand that?任何人都可以帮助理解吗?

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) 

In this part of your code:在这部分代码中:

readIORef (n,r2) 

(n,r2) is not a IORef. (n,r2)不是 IORef。 r2 is an IORef, so you this is legal: r2是一个 IORef,所以你这是合法的:

readIORef r2

So how about trying this:那么试试这个怎么样:

  1. read the IORef r2 getting a value读取 IORef r2 获取值
  2. return the pair (n, ...) where ... is the value you got in step 1返回对 (n, ...) 其中 ... 是您在步骤 1 中获得的值

First, indent the arguments of while , otherwise they are new statements.首先,缩进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) 

Second, the while look roughly corresponds to the imperative code:其次,while 的外观大致对应于命令式代码:

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

This makes no sense: why the recursive call?这毫无意义:为什么要递归调用? Surely you know how to write the factorial in imperative style in a conventional imperative language;您肯定知道如何用传统命令式语言以命令式风格编写阶乘; start from that and convert it to Haskell.从那开始并将其转换为 Haskell。

I see two problems that are preventing compilation.我看到两个阻止编译的问题。 The first is that fact (v2-1) has type IO (Integer, Integer) , yet you are trying to multiply it by v2 :: Integer .第一个是fact (v2-1)具有类型IO (Integer, Integer) ,但您试图将其乘以v2 :: Integer You need to sequence fact (v2-1) like you sequence readIORef r2 , the multiply by the second component of the pair.您需要对fact (v2-1)进行排序,就像对readIORef r2排序readIORef r2 ,乘以对的第二个分量。

Second, you are misusing readIORef .其次,您滥用了readIORef You can see it's signature here .你可以在这里看到它的签名。 It takes an IORef a , not a pair.它需要一个IORef a ,而不是一对。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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