2013-07-18 83 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