2015-10-22 122 views
-3

我正在做IO monad haskell中的階乘函數。 我跟着例子mod3爲了做IO monad的階乘函數。 我不明白爲什麼我的代碼是錯的。 我想看看n> = 1,然後對n進行階乘。 最後添加到(n,r2)並返回。 任何人都可以幫助理解嗎?IO monad haskell中的階乘函數

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) 
+0

你的代碼做了什麼或不做什麼? – crockeea

+0

你能解釋一下你正在努力完成什麼嗎?你爲什麼使用'IORef's? – crockeea

+1

我的代碼是計算一個數字的階乘,例如,事實4,它返回一個列表,(4,24)。 4是用戶給出的數字,24是4! – njkdsaw

回答

1

在您的這部分代碼:

readIORef (n,r2) 

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

readIORef r2 

因此,如何嘗試這樣的:

  1. 閱讀IOREF R2得到一個值
  2. 回報組(N,...)其中...是您在步驟1中獲得的值
0

我看到兩個阻止編譯的問題。首先是fact (v2-1)有類型IO (Integer, Integer),但是你想要乘以v2 :: Integer。您需要按順序排列fact (v2-1),就像序列號readIORef r2,乘以該對的第二個分量。

二,您誤用readIORef。你可以看到它的簽名here。它需要一個IORef a,而不是一對。

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 r2 >= 1 : 
    r2 = r2 * fact(r2-1) 

這是沒有意義的:爲什麼遞歸調用?當然,你知道如何用傳統的命令式語言寫出命令式的因式分解法;從此開始並將其轉換爲Haskell。