2013-07-18 71 views
5

Tôi đang có một Trạng thái Haskell nhỏ ở đây. Tôi đang cố gắng viết hai hàm với monads. Thứ nhất có nghĩa vụ lặp qua một hàm miễn là điều kiện là đúng cho đầu vào/đầu ra của hàm. Thứ hai là một trong những nghĩa vụ phải sử dụng đầu tiên để có một số như đầu vào và viết nó như là đầu ra cho đến khi bạn nhập vào một không gian.Khi vòng lặp trong Haskell với điều kiện

Tôi bị kẹt với điều này, bất kỳ trợ giúp nào?

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

Vì vậy, câu hỏi của bạn là câu hỏi nào? Bạn bị mắc kẹt ở đâu, cái gì không hiệu quả? – leftaroundabout

+0

Cả hai chức năng này thậm chí không biên dịch được, và tôi khá chắc chắn rằng họ sẽ không làm những gì tôi muốn họ làm anyways. Tôi chỉ không biết cách viết nó trong một phiên bản làm việc. Tôi về cơ bản cố gắng để có được một vòng lặp while làm việc với một điều kiện. Vì vậy, ví dụ: 'trong khi lẻ (hình vuông 3)' nên kiểm tra nếu hình vuông 3 là lẻ, sau đó sử dụng kết quả của hình vuông 3 = 9 và làm 'trong khi lẻ (hình vuông 9)' v.v. Về mặt kỹ thuật, không cần x, nó chỉ hoạt động với 'trong khi chức năng điều kiện ' – Chris

Trả lời

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() 

Một số lưu ý:

  • Sử dụng if x then True else False là không cần thiết, đó là tương đương với chỉ x.
  • Tương tự, if x == True ... là dự phòng và tương đương với if x ....
  • Bạn cần phải phân biệt giữa hành động IO và kết quả của chúng. Ví dụ, nếu yo làm

    do 
        i <- getChar 
        ... 
    

    sau đó trong ... i đại diện cho kết quả của hành động, một nhân vật, vì vậy i :: Char. Nhưng getChar :: IO Char chính là hành động. Bạn có thể xem nó như một công thức trả về Char khi được thực hiện. Bạn có thể chuyển công thức xung quanh thành các hàm vv, và nó chỉ được thực hiện khi được thực hiện ở đâu đó.

  • while được gọi là funktion hai lần, có thể không phải là ý của bạn - nó sẽ đọc một ký tự hai lần, kiểm tra ký tự đầu tiên và trả về ký tự thứ hai. Hãy nhớ rằng, funktion của bạn là một hành động, vì vậy mỗi lần bạn "gọi" hành động (ví dụ bằng cách sử dụng <- funktion ... trong ký hiệu do), hành động sẽ được chạy lại. Vì vậy, nó khá nên một cái gì đó giống như

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

    (Mã của tôi là hơi khác nhau, nó sẽ kiểm tra đối số được truyền cho nó.)

+0

Tuyệt vời, cảm ơn bạn. Tôi hiểu làm thế nào bạn đã làm power2, làm cho rất nhiều ý nghĩa. Tôi vẫn không chắc chính xác những gì đang xảy ra trong khi đó, tho. Tại thời điểm nào chính xác thì không được kiểm tra nếu điều kiện là đúng? – Chris

+0

@Chris Nó kiểm tra nếu điều kiện giữ cho đối số của nó về kiểu 'a' trước khi làm bất cứ điều gì khác, giống như câu lệnh' while' trong các ngôn ngữ chức năng. Điều này được thực hiện bằng cách sử dụng [guards] (http://learnyouahaskell.com/syntax-in-functions#guards-guards), thường được ưu tiên hơn 'if/then/else'. Dòng '| ca ngợi x = do ... 'nói _if điều kiện' được ca ngợi x' là đúng, tiếp tục với ..._. Dòng tiếp theo '| nếu không = ... 'bao gồm tất cả các trường hợp còn lại (bởi vì' nếu không' chỉ là một từ đồng nghĩa với 'True', vì vậy' nếu không' là một điều kiện luôn được thỏa mãn). –

3

Đối với một phiên bản tinh khiết:

{-# 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 

cho 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' 

xem al như vậy:

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

Một phiên bản thuần túy khác) 'trong khi p = cho đến khi (không phải. P)' – wowofbob

Các vấn đề liên quan