10
\$\begingroup\$

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 '.' '+')
asked Nov 26, 2015 at 21:28
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

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 '.' '+'))
answered Nov 27, 2015 at 11:09
\$\endgroup\$
5
  • \$\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\$ Commented 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 as puts in C. From a performance point of view, you try to avoid many I/O calls (I/O, not IO) although this isn't really measurable in this small program. \$\endgroup\$ Commented Nov 27, 2015 at 16:58
  • \$\begingroup\$ cool performance trick :) What about the general type? \$\endgroup\$ Commented 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 define head :: [Int] -> Maybe Int. But head :: [a] -> Maybe a is a lot more useful. \$\endgroup\$ Commented 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\$ Commented Nov 27, 2015 at 17:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.