2016-08-14 73 views
0

我試圖寫在Haskell的函數,將採取一個整數,並返回字符串返回一個連接字符串在Haskell遞歸函數

例如,一個級聯(次輸入的號碼),

輸入: 3

輸出:HI1 \ nhi2 \ nhi3

main = do 

    let str = func 2 "" 
    putStrLn str 

func :: Int -> String -> String 
func i str = do 
     if i>(-1) 
      then do 
       str ++ "hi" ++ (show i) 
       func (i-1) str 

     else str 

感謝你!

+0

'FUNC我STR = unlines $地圖(\的J - > STR ++ 「喜」 ++播放J)1..i]' – Alec

+0

謝謝亞歷克,工程:) – David

回答

0

使你的代碼的「工作」(後來我將解釋雙引號),最簡單的方法就是直接調用func與連接字符串作爲參數,無中間步驟:

func :: Int -> String -> String 
func i str = do 
     if i > (-1) 
      then func (i-1) (str ++ "hi" ++ (show i) ++ "\n")  
      else str 

我也將換行符添加到輸出中,這意味着結果的最後一個字符將成爲新行。因此,最好寫

let str = func 2 "" 
putStr str 

這樣你就可以避免在最後一個額外的新行。

我的第一句話雙引號中寫道「作品」,因爲我的代碼打印

hi2 
hi1 
hi0 

您需要修改func從而使線以相反的順序打印。提示:您可以將行存儲在列表中,並在最後反轉列表。

P.S.我不確定零是否應該是有效的後綴。如果不是,那麼您必須更改您的if聲明中的條件。

+0

有在執行'func'時不需要任何'do'符號。 – Jubobs

+0

感謝您的注意,我會更正這一點。 – Kapol

+0

謝謝kapol :) – David

2

這是一個更慣用的溶液比使用if-else

,將採取的整數,並返回一個連接起來的功能(次數輸入)串

func :: Int -> String -> String 
func 0 s = "" 
func n s = s ++ func (n - 1) s 

main = putStrLn (func 3 "hi") 

輸出

hihihi 
+0

承認,謝謝noamik :) – David

1

我想知道'對數'解決方案更快:

main = putStrLn $mul 7 "Hi" 

mul :: Int -> String -> String 
mul 0 _ = "" 
mul 1 s = s 
mul _ "" = "" 
mul n s = let 
      (q, r) = n `quotRem` 2 
      s' = mul q s 
    in (if r == 1 then s else "") ++ s' ++ s' 
+0

這執行較少的遞歸調用,但's'++ s''的代價是O(n),這應該否定這種優勢。我希望這會使用雙倍的內存,如果不是更糟的話。在一般情況下,用大的左列表參數調用'++'不是一個好主意,因爲該列表必須被複制以產生結果。 – chi

+0

連接列表有更好的方法:將它們打包成函數,將它們與'.'運算符合並,並在完成時應用'[]'。您可以使用'id'來表示空字符串,並將字符串's'打包成如下函數:'(s ++)'。這有助於確保在任何給定時間只有一次調用'++'在調用堆棧中。 –