2013-07-18 2 views
5

У меня есть небольшая ситуация с Хаскеллом здесь. Я пытаюсь написать две функции с монадами. Предполагается, что первый из них выполняет итерацию по функции, если условие истинно для ввода/вывода функции. Второй должен использовать первый, чтобы взять номер в качестве ввода и записать его в качестве вывода, пока вы не введете пробел.Пока петля в 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, работающий с условием. Например, 'while нечетный (квадрат 3)' должен проверить, является ли квадрат 3 нечетным, а затем использовать результат квадрата 3 = 9 и сделать 'while odd (square 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 является действием, поэтому каждый раз, когда вы «вызываете» действие (например, используя <- funktion ... в нотации do), действие запускается снова. Так оно и должно скорее быть что-то вроде

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

    (Мой код несколько иной, он проверяет аргумент, передаваемый на него.)

+0

Удивительно, спасибо. Я понимаю, как вы сделали power2, имеет большой смысл. Я все еще не уверен, что именно происходит во время, тo. В какой момент точно выполняется проверка, верно ли условие? – Chris

+0

@Chris Он проверяет, выполняется ли условие для его аргумента типа 'a' перед тем, как делать что-либо еще, так же, как и инструкции' while' в функциональных языках. Это делается с помощью [охранников] (http://learnyouahaskell.com/syntax-in-functions#guards-guards), что часто предпочтительнее над 'if/then/else'. Линия '| praed x = do ... 'говорит, что условие« praed x »истинно, продолжайте .... Следующая строка '| в противном случае = ... 'охватывает все остальные случаи (потому что' иначе 'является просто синонимом для 'True', поэтому' other' является условием, которое всегда выполняется). –

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 

по Монако:

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' 

см. 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 = до (не. P)' – wowofbob

Смежные вопросы