而Haskell中的循环具有条件

时间:2013-07-18 09:29:39

标签: loops haskell while-loop

我在这里有一点Haskell情况。我正在尝试用monad编写两个函数。 只要条件对于函数的输入/输出为真,第一个就应该迭代一个函数。第二个应该使用第一个作为输入的数字并将其作为输出写入,直到您输入空格。

我坚持这个,有什么帮助?

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

2 个答案:

答案 0 :(得分: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是一项操作,因此每次“调用”操作时(例如,使用<- funktion ...表示法中的do),操作都会再次运行。所以它应该像

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

    (我的代码有些不同,它会检查传递给它的参数。)

答案 1 :(得分: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

对于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'

另见:

http://hackage.haskell.org/package/monad-loopshttp://hackage.haskell.org/package/loop-whilehttp://hackage.haskell.org/package/control-monad-loop

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