2016-03-14 142 views
0

我是Haskell的新手。我试图通过按此顺序打印“Hi”来改进我的代码。例如,n = 4,输出:在Haskell中打印字符串'N'次

Hi 
Hi Hi 
Hi Hi Hi 
Hi Hi Hi Hi 

我当前的代码是:

printHi :: Integer -> String 
printHi n = concat["Hi" | n <- [0..n-1]] 

,其输出是:

Hi Hi Hi Hi 

如何,我就能任何提示执行此任务?由于

+0

所以你实际上想返回'你好\ nHi你好\ nHi你好你好\ n你好你好\ n''? – chepner

+2

那么,如果'printHi n'打印出“Hi”'n'次,那么你只需要调用'printHi 1'4。 –

回答

1

这里是打印“喜” 4倍的方式....

putStrLn $ unwords $ replicate 4 "hi" 

这里是打印的三角形态你在上面

显示
putStrLn $ unlines $ map (unwords . flip replicate "hi") [1..4] 
+1

'unlines'似乎...过多。 'traverse_ putStrLn'可以做到这一点,甚至可以在'map'的参数中加入'(++“\ n”).'。 – dfeuer

+0

@dfeuer'unlines'如何显得过度?由于尾随的换行符? 'putStr。 unlines'会解决这个问题。另外,'traverse_ putStrLn'会产生正确的输出,但是如果实际的目标是'Int - > String'类型的函数,无论如何都必须重写它。 – Zeta

+0

@Zeta,是的,我把'unlines'与更复杂的'unwords'混淆了。抱歉。 – dfeuer

2

有两种可能的方式方法。

一个是建立一个大的字符串,包括所有"Hi"部分和所需的换行符。之后,打印字符串就足够了。 (这是jamshidh在上面做的)。

或者,可以使用更“强制性”的方法并使用循环。例如,

import Control.Monad 

foo :: IO() 
foo = forM_ [1..100] $ \i -> 
     putStrLn ("The current value of i is" ++ show i) 

将打印数从1100,每一个短消息。将此与您的案例相适应留作练习。

flip traverse_也可以用来代替forM_

的第一个样式可能更灵活,使制作的字符串可以在非IO环境中被重用。但是,如果我们确信我们永远不会需要该字符串用于其他目的而不是打印它,第二种方法就足够了。

0

听起来像你想要使用'scanl'。 scanl就像是一个折叠,只是它保存了中间结果 。如果你有一个列表,如[“你好”,“你好”,“你好”,“你好”]。 与(++)相比,会产生像“HiHiHiHi”这样的字符串。 随着scanl中间结果也将保存 - > [“”,“你好”,“的HiHi” ......等等。现在

,如果我是无耻地把你的代码并修改它有点 位的结果可能是这样的:

printHi :: Integer -> [String] 
printHi n = scanl (++) "" ["Hi " | n <- [0..n-1]] 

我添加了一个空间为“Hi”,使其在 你的问题看起来更有点像。所以结果将是这样一个列表:

["", "Hi ", "Hi Hi ", "Hi Hi Hi ", "Hi Hi Hi Hi "] 

希望这会回答你的问题。

亲切的问候,

编辑

如果您使用的功能“unlines”结果列表中就会产生 所需出来把作为问题,当然还有空字符串声明如果您希望这样做,可以使用“尾巴”删除列表开头的 。