2013-07-18 85 views
5

我在這裏有一個小哈斯克爾情況。我試圖用monad編寫兩個函數。 只要條件對於函數的輸入/輸出爲真,首先應該遍歷一個函數。第二個應該使用第一個數字作爲輸入,並將其寫入輸出,直到輸入空格。雖然在Haskell循環條件

我堅持這一點,任何幫助?

module Test where 

while :: (a -> Bool) -> (a -> IO a) -> a -> IO a 
while praed funktion x = do 
         f <- praed (funktion x) 
         if f == True then do 
              y <- funktion x 
              while praed funktion y 
         else return x 



power2 :: IO() 
power2 = do putStr (Please enter a number.") 
      i <- getChar 
      while praed funktion 
      where praed x = if x /= ' ' then False else True 
        funktion = i 
+3

那麼,哪一個是你的問題呢?你卡在哪裏,什麼不行? – leftaroundabout

+0

這兩個函數都沒有編譯,我敢肯定,他們不會做我希望他們做的事情。我只是不知道如何在工作版本中編寫它。我基本上試圖讓一個while循環處理一個條件。因此,例如, '而奇數(方格3)' 應該測試方格3是否是奇數,然後使用方格3 = 9的結果並且在奇數(方格9)的情況下使用 '等等。 從技術上講,它不應該需要一個x,它應該只與 ''同時條件函數' – Chris

回答

11
import Control.Monad 

while :: (a -> Bool) -> (a -> IO a) -> a -> IO a 
while praed funktion x 
    | praed x = do 
     y <- funktion x 
     while praed funktion y 
    | otherwise = return x 


power2 :: IO() 
power2 = do 
    putStr "Please enter a number." 
    i <- getChar 
    let praed x = x /= ' ' 
    let f x = do 
     putChar x 
     getChar 
    while praed f '?' 
    return() 

一些注意事項:

  • 使用if x then True else False是多餘的,它相當於只是x
  • 同樣if x == True ...是多餘的,相當於if x ...
  • 您需要區分IO操作及其結果。例如,如果喲做

    do 
        i <- getChar 
        ... 
    

    然後... i代表的動作,角色,所以i :: Char的結果。但是getChar :: IO Char是行動本身。您可以將其視爲執行時返回Char的配方。你可以將配方傳遞給函數等,只有在某個地方執行時纔會執行。

  • 你的while調用了funktion兩次,這可能不是你想要的 - 它會讀一個字符兩次,檢查第一個並返回第二個。請記住,您的funktion是一個動作,因此每次您「調用」該動作時(例如通過使用do表示法中的<- funktion ...),該動作會再次運行。所以它應該是像

    do 
        y <- funktion x 
        f <- praed y 
        -- ... 
    

    (我的代碼有所不同,它會檢查傳遞給它的參數。)

+0

真棒,謝謝。我明白你是如何做到這一點的,這很有道理。我仍然不確定到底發生了什麼,tho。確切地說,在哪個點上檢查條件是否正確? – Chris

+0

@Chris在做任何其他事情之前,它會檢查條件是否適用於其類型爲「a」的參數,就像功能語言中的while語句一樣。這是通過使用[guard](http://learnyouahaskell.com/syntax-in-functions#guards-guards)來完成的,通常比'if/then/else'更可取。行'| praed x = do ...'說,如果'praed x'是真的,繼續..._。下一行'|否則= ...'涵蓋所有其他情況(因爲'否則'只是'真'的同義詞,否則'總是滿足的條件]。 –

3

對於純版本:

{-# LANGUAGE BangPatterns #-} 

while :: (a -> Bool) -> (a -> a) -> a -> a 
while p f = go where go !x = if p x then go (f x) else x 

test1 :: Int 
test1 = while (< 1000) (* 2) 2 
-- test1 => 1024 

for monadic:

import Control.Monad 

whileM :: (Monad m, MonadPlus f) => (a -> m Bool) -> m a -> m (f a) 
whileM p f = go where 
    go = do 
    x <- f 
    r <- p x 
    if r then (return x `mplus`) `liftM` go else return mzero 

test2 :: IO [String] 
test2 = whileM (return . (/= "quit")) getLine 
-- *Main> test2 
-- quit 
-- [] 
-- *Main> test2 
-- 1 
-- 2 
-- 3 
-- quit 
-- ["1","2","3"] 

power2 :: IO (Maybe Char) 
power2 = whileM (return . (/= 'q')) getChar 
-- *Main> power2 
-- q 
-- Nothing 
-- *Main> power2 
-- 1 
-- 2 
-- 3 
-- q 
-- Just '\n' 

see al所以:

http://hackage.haskell.org/package/monad-loops,http://hackage.haskell.org/package/loop-while,http://hackage.haskell.org/package/control-monad-loop

http://www.haskellforall.com/2012/01/haskell-for-c-programmers-for-loops.html

+5

另一個純版本) 'while p = until(not。p)' – wowofbob