簡體   English   中英

IO monad haskell 中的階乘函數

[英]factorial function in the IO monad haskell

我正在 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) 

在這部分代碼中:

readIORef (n,r2) 

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

readIORef r2

那么試試這個怎么樣:

  1. 讀取 IORef r2 獲取值
  2. 返回對 (n, ...) 其中 ... 是您在步驟 1 中獲得的值

首先,縮進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。

我看到兩個阻止編譯的問題。 第一個是fact (v2-1)具有類型IO (Integer, Integer) ,但您試圖將其乘以v2 :: Integer 您需要對fact (v2-1)進行排序,就像對readIORef r2排序readIORef r2 ,乘以對的第二個分量。

其次,您濫用了readIORef 你可以在這里看到它的簽名。 它需要一個IORef a ,而不是一對。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM