Print diamond of any size I'm trying to print a diamond of asterisks of an arbitrary size. I'm new to F#, so I'm interested in virtually any feedback, but especially adherence to idioms, convention, and functional orientation.

module Diamond
open System

let rangeWithInverse (max) = 
    List.zip [ 1 .. max ] [ max .. -1 .. 1]

let listAscDesc (list) = 
    list @ (list |&gt; List.rev |&gt; List.skip 1)

let starsAndSpacesString (stars: int, spaces: int): string =
    String.replicate spaces " " + String.replicate ((stars * 2) - 1) "*"

let diamond =
    rangeWithInverse 18
        |&gt; listAscDesc
        |&gt; Seq.map starsAndSpacesString
        |&gt; Seq.reduce (fun a b -&gt; a + "\n" + b)

[&lt;EntryPoint&gt;]
let main argv = 
    diamond |&gt; printfn "%s"
    0
It's hard to comment on it. It seems OK to me - maybe a little to much list manipulation. I'm not sure if string concat with + is acceptable practice in F# but in general it's not. For fun I've tried with my own version with use of recursion:

let newDiamond n =
    let rec print nn f = 
        if nn &lt;= n &amp;&amp; nn &gt; 0 then
            let spaces = String.replicate ((n - nn) / 2) " "
            sprintf "%s%s%s\n%s" spaces (String.replicate nn "*") spaces (print (f nn) f)
        else
            ""
    let add x = x + 2
    let subt x = x - 2
    let dn = if n % 2 = 0 then 3 else 2
    sprintf "%s%s" (print 1 add) (print (n - dn) subt)

[&lt;EntryPoint&gt;]
let main argv = 
    newDiamond 36 |&gt; printfn "%s"    
    Console.ReadLine() |&gt; ignore
    0


Version with pattern match instead of if:

let newDiamond n =
    let rec print nn f = 
        match nn with
        | x when x &lt;= 0 || x &gt;= n + 1 -&gt; ""
        | _ -&gt; let spaces = String.replicate ((n - nn) / 2) " "
               sprintf "%s%s%s\n%s" spaces (String.replicate nn "*") spaces (print (f nn) f)

    let add x = x + 2
    let subt x = x - 2
    let dn = if n % 2 = 0 then 3 else 2
    sprintf "%s%s" (print 1 add) (print (n - dn) subt)


It's possible but does it add any good?

EDIT:

A condensed solution could be:

let newDiamond n = 
    let topNs = [1..2..n]
    let diamondNs = List.append topNs (topNs |&gt; List.rev |&gt; List.tail)

    let createLine x = 
        sprintf "%s%s" (String.replicate ((n - x) / 2) " ") (String.replicate x "*")

    (diamondNs |&gt; Seq.mapFold (fun strs x -&gt; ("", sprintf "%s\n%s" strs (createLine x))) "") |&gt; snd


However none of the solutions are very performant if diamond size is increased (> 2000) due to the concatenation of strings. In that respect a good old iterative solution is preferable:

let newDiamond n =
    let createLine = (fun x -&gt; sprintf "%s%s" (String.replicate ((n - x) / 2) " ") (String.replicate x "*"))
    let topHalf = [ 1..2..n ]
    let indices = topHalf @ (topHalf |&gt; List.rev |&gt; List.tail)
    seq { for ln in indices do
            yield createLine ln } |&gt; Seq.iter (printfn "%s")


A gentle "refactoring" of BadHeuristics code:

let rangeWithInverse max = 
    List.zip [ 1 .. max ] [ max .. -1 .. 1]

let listAscDesc list = 
    list @ (list |&gt; List.rev |&gt; List.tail) // tail instead of skip 1

let starsAndSpacesString (stars, spaces) =
    sprintf "%s%s" (String.replicate spaces " ") (String.replicate ((stars * 2) - 1) "*") // sprintf instead of ""+""

let diamond n =
    rangeWithInverse (n / 2)
        |&gt; listAscDesc
        |&gt; Seq.map starsAndSpacesString
        |&gt; Seq.reduce (fun a b -&gt; sprintf "%s\n%s" a b) // sprintf instead of ""+""