2016-06-07 51 views
1

將輸入作爲字符串並使用do-notation打印10次?haskell打印10次輸入字符串,do-notation

print10Times :: String -> IO() 
print10Times name = putStrLn $ repeat 10 name 

main :: IO() 
main = do 
    putStrLn "What is your name?" 
    name <- getLine 
    print10Times name 

回答

3

repeat只接受一個參數並無限期地重複它。您可能正在尋找take 10 $ repeat name

如果要打印一個列表,最好使用mapM_對列表中的每個元素映射putStrLn。嘗試了這一點:

print10Times :: String -> IO() 
print10Times name = mapM_ putStrLn $ take 10 $ repeat name 

或者,更簡潔:

print10Times = mapM_ putStrLn . take 10 . repeat 
+3

'複製10'是一個更好的版本的'需要10。 repeat'。 – amalloy

5

您可以使用replicateM_這一點。

Λ: :t replicateM_ 
replicateM_ :: Monad m => Int -> m a -> m() 
Λ: do { putStrLn "what is your name?" ; name <- getLine ; replicateM_ 10 (putStrLn name) } 
what is your name? 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
none of your business 
+0

用':set + m'可以在ghci中啓用多線路輸入模式。 – karakfa

2

你絕對可以使用replicateM_@pdexter建議,或者您可以使用遞歸改寫:

print10Times :: String -> IO() 
print10Times = printNTimes 10 

printNTimes :: Int -> String -> IO() 
printNTimes n name | n <= 0 = return() 
        | otherwise = do 
         putStrLn name 
         printNTimes (n-1) name 

main :: IO() 
main = do 
    putStrLn "What is your name?" 
    name <- getLine 
    print10Times name 

print10Times簡單地重定向控制以恆定10(應該打印的次數,以printNTimes )。然後在每次打印名稱時執行遞減,如果計數器達到0,則完成return()

這有點重塑replicateM_其可以被定義爲:

replicateM_ :: (Monad m, Num n, Ord n) => n -> m a -> m() 
replicateM_ n f = loop n 
    where loop i | i <= 0 = return() 
       | otherwise = f >> loop (i-1)