2016-08-14 69 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 ++)'。这有助于确保在任何给定时间只有一次调用'++'在调用堆栈中。 –