Write a function
Int -> Char -> Char -> [String]
that will create the appropriate pattern.For example:
mapM_ putStrLn (pattern 48 '.' '+')
................................................ .+..+..+..+..+..+..+..+..+..+..+..+..+..+..+..+. +.++.++.++.++.++.++.++.++.++.++.++.++.++.++.++.+ ................................................
This idea is inspired by Writing nested for loops to produce certain output (but more general).
I am pretty satisfied with my code to solve this problem:
pattern :: Int -> Char -> Char -> [String]
pattern len a b = map (take len . cycle) [[a], [a, b, a], [b, a, b], [a]]
main :: IO()
main = mapM_ putStrLn (pattern 48 '.' '+')
1 Answer 1
Seems fine. However, depending on the context and the rest of the program, you can relax pattern
's type:
pattern :: Int -> a -> a -> [[a]]
Also, since every putStrLn
is basically hPutStrLn stdout
, you could first glue all lines together with unlines
and then print them with a single action:
main = putStr (unlines (pattern 48 '.' '+'))
-
\$\begingroup\$ I see your suggestions but fail to understand the reasoning about them... why is a general type better? Why is a single action better? \$\endgroup\$Caridorc– Caridorc2015年11月27日 16:47:42 +00:00Commented Nov 27, 2015 at 16:47
-
1\$\begingroup\$ @Caridorc: The most important parts of the answer are its first two words: Your code is fine. There are just some stylistic choices/alternatives you can consider. However, about the single action:
putStrLn
is basically the same asputs
in C. From a performance point of view, you try to avoid many I/O calls (I/O, notIO
) although this isn't really measurable in this small program. \$\endgroup\$Zeta– Zeta2015年11月27日 16:58:56 +00:00Commented Nov 27, 2015 at 16:58 -
\$\begingroup\$ cool performance trick :) What about the general type? \$\endgroup\$Caridorc– Caridorc2015年11月27日 17:00:09 +00:00Commented Nov 27, 2015 at 17:00
-
1\$\begingroup\$ @Caridorc: You cannot use
pattern 48 1 2
in your original program ^^. The consensus in Haskell is: if you can make a function more general (without loosing something), make it more general. For example, you could definehead :: [Int] -> Maybe Int
. Buthead :: [a] -> Maybe a
is a lot more useful. \$\endgroup\$Zeta– Zeta2015年11月27日 17:01:06 +00:00Commented Nov 27, 2015 at 17:01 -
\$\begingroup\$ Yeah, I meant it to be a text pattern, but it is always nice to know when things could be more general. \$\endgroup\$Caridorc– Caridorc2015年11月27日 17:02:30 +00:00Commented Nov 27, 2015 at 17:02
Explore related questions
See similar questions with these tags.