# Generating alphanumeric combinations

I was happy with my shell script that needed to generate alphanumeric combinations of length N (in this case, 3)

for i in {a..z}{a..z}{a..z}; do ...


Now I became less happy when I needed alphanumeric combinations (specially if I choose a larger value for N)

for i in {0..9}{a..z}{a..z} \
{a..z}{0..9}{a..z} \
{a..z}{a..z}{0..9} \
{a..z}{a..z}{a..z} \
{0..9}{0..9}{a..z} \
{0..9}{a..z}{0..9} \
{a..z}{0..9}{0..9} \
{0..9}{0..9}{0..9}; do ...


So I decided to write it in Haskell:

import Data.List
c 0 _ = [[]]
c n xs = [ y:ys | y:xs' <- Data.List.tails xs, ys <- c (n-1) xs']
main = sequence_ . map putStrLn . c 3 $['a' .. 'z'] ++ ['0' .. '9']  Now, I couldn't find a way to incorporate the above code in my shell script, so I had to reduce it to a one-liner to run with ghc -e, finally giving me the code I have right now: for i in$(ghc -e "
let c n l = if n == 0 then [[]] else \
[y:s | y:q <- Data.List.tails l, s <- c (n-1) q] in
sequence_. map putStrLn . c 3 $['a'..'z'] ++ ['0'..'9']"); do ...  Now, I actually like this style (elsewhere I have inline calls to awk too, etc). But I think this code is too big and too ugly; for example, I'm using if n == 0 instead of guards, etc. Haskell is supposed to be a lot more concise than that. My only requirement is that I may want to change the length to be larger than 3, but also ['a'..'z'] ++ ['0'..'9'] to another set (perhaps to include - or _). ## migrated from codegolf.stackexchange.comMay 19 '15 at 0:57 This question came from our site for programming puzzle enthusiasts and code golfers. • Does your code work the way it should as presented? There are ellipsis at the end of two code blocks, which hints that this could be stub code. Please clarify! – Phrancis May 19 '15 at 1:09 • Yes, the code actually works fine (it's part of a larger script). It's just that I feel that this should be a simpler one-liner; at the very least, I wanted to eliminate the if n == 0 .. else .. by turning the let binding into a where binding, but I couldn't figure out how to write it in one line. – darque May 19 '15 at 1:31 • PS: this was moved to Code Review by someone else, but the question isn't "is this style fine" but "how could something like this be written in a more concise way" – darque May 19 '15 at 1:33 • Is it ok that you shell code and haskell code produce different results? I.e. cross product vs. set of subsequences. – max taldykin May 19 '15 at 6:39 • Actually even easier, runghc --. – bisserlis May 19 '15 at 20:22 ## 1 Answer In Haskell you can always use ;, see The Haskell Report. So your original code could be written as an one-liner as follows: import Data.List ; c 0 _ = [[]] ; c n xs = [ y:ys | y:xs' <- tails xs, ys <- c (n-1) xs'] ; main = mapM_ putStrLn . c 3$ ['a' .. 'b'] ++ ['0' .. '1']


A small improvement - sequence_ . map f is mapM_ f.

Of course you'll lose the nice indentation.

IF you don't mind repeating elements (which is what you have in the original shell script), you can use replicateM:

import Control.Monad
main = mapM_ putStrLn . replicateM 3 \$ ['a' .. 'b'] ++ ['0' .. '1']