2013-07-18 30 views
5

私はここに少しハスケルの状況があります。私はモナドで2つの関数を書こうとしています。 最初に、関数の入出力に対して条件が真である限り、関数を反復することになっています。 2番目のものは最初のものを使って数字を入力し、スペースを入力するまで出力として書き出すものとします。条件付きのハスケルのwhileループ

私はこれに助けられましたか?

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 odd(square 3) ' は、正方形3が奇数であるかどうかをテストし、次に正方形3 = 9の結果を使用して ' while odd(square 9) 'などを実行します。 技術的にはxが必要ではありません。 'while condition function' – 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アクションとその結果を区別する必要があります。ヨーヨーがで... iその後、

    do 
        i <- getChar 
        ... 
    

    を行う場合たとえば、アクション、キャラクター、そうi :: Charの結果を表します。しかし、getChar :: IO Charはアクションそのものです。実行するとCharを返すレシピとして表示できます。レシピを関数などに渡すことができ、どこかで実行された場合にのみ実行されます。

  • whilefunktion 2回、おそらく意図したとおりではありません。文字を2回読み、最初の文字をチェックして2番目の文字を返します。 funktionはアクションですので、アクションを呼び出すたびに(doの表記で<- funktion ...を使用するなど)アクションが再度実行されることを覚えておいてください。だから、むしろ

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

    のようなものでなければなりません(私のコードは多少異なっている、それはそれに渡される引数をチェックします。)純粋なバージョンについては

+0

素晴らしいです、よろしくお願いします。私はあなたがパワー2をどのようにしたのか理解しています。私はまだ、正確に何が起こっている間、tho。条件が真であるかどうかを正確にチェックするのはどの時点ですか? – Chris

+0

@Chris関数型言語の 'while'文のように、' a'型の引数が条件を満たしているかどうかをチェックします。これは[guards](http://learnyouahaskell.com/syntax-in-functions#guards-guards)を使って行います。これは、 'if/then/else'よりもしばしば好ましい方法です。 '| praed x = do ... 'は、' 'praed x''が真であれば、...と進んでいます。次の行 '| 'otherwise'は' True'の同義語であるため、 'otherwise'は常に満たされる条件です)。 –

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' 

so:

http://hackage.haskell.org/package/monad-loops,http://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

+5

別の純粋なバージョン) 'while p = until(not。p)' – wowofbob