First attempt at doing anything F#-y from a very heavy C# background, think I've grasped the fundamentals of FP, but always good to get other eyes on it:namespace FSharp.GameOfLifeopen Systemopen System.Drawingmodule Array2D =    let toArray (arr: 'T [,]) = arr |> Seq.cast<'T> |> Seq.toArraymodule Array =    let count (predicate: 'T -> bool) (arr: 'T[]) = arr |> Array.filter(predicate) |> Array.lengthmodule Game =    let (<&>) f g = (fun x -> f x && g x)    type Cell (position) =         member this.Position = position        member val IsAlive = false with get, set    and Board (width : int, height : int) =         let grid = Array2D.init width height (fun x y -> Cell(System.Drawing.Point(x, y)))        let withinBounds (x : int, y : int) =            let insideWidth = width > x && x >= 0            let insideHeight = height > y && y >= 0            insideWidth && insideHeight        let isSamePosition (cell : Cell, x : int, y : int) =             cell.Position = Point(x, y)        let getNeighbours (grid : Cell[,]) (cell : Cell) =            let isDifferentPosition (x, y) = not (isSamePosition (cell, x, y))            let positionModifiers = Array2D.initBased -1 -1 3 3 (fun x y -> (cell.Position.X + x, cell.Position.Y + y))            positionModifiers |> Array2D.toArray |> Array.filter (withinBounds <&> isDifferentPosition) |> Array.map (fun (x, y) -> grid.[x, y].IsAlive)        member this.Grid with get() = grid        member this.Tick() =             let cellWithNeighbourStates = this.Grid |> Array2D.map (fun cell -> (cell, (getNeighbours this.Grid cell))) |> Array2D.toArray            cellWithNeighbourStates |> Array.iter (fun (cell, neighbours) ->                 let liveNeighbours = neighbours |> Array.count (fun c -> c = true)                 if cell.IsAlive then                    cell.IsAlive <- 2 = liveNeighbours || 3 = liveNeighbours                else                    cell.IsAlive <- 3 = liveNeighbours                )        member this.SetAlive(cells : list<int * int>) =            cells |> List.iter (fun (x, y) -> this.Grid.[y, x].IsAlive <- true)        override this.ToString() =             let structs = this.Grid |> Array2D.map (fun cell -> if cell.IsAlive then [] else ())            let asRows = [|0..(height - 1)|] |> Array.map (fun row -> structs.[0.., row] |> Array.fold (fun acc elem -> sprintf %s%s acc elem) Environment.NewLine)            asRows |> Array.fold (fun acc elem -> sprintf %s%s acc elem) Environment.NewLineCan be tested as such:open FSharp.GameOfLife.Game[<EntryPoint>]let main argv =     let board = Board (10, 10)    //standard ocilator    let x = board.SetAlive([        (1, 1)        (1, 2)        (2, 1)        (2, 2)        (3, 3)        (3, 4)        (4, 3)        (4, 4)    ])    printf %s (board.ToString())    [|0..2|] |> Array.iter (fun _ ->         board.Tick()        printf %s (board.ToString())    )    System.Console.ReadKey() |> ignore    0 // return an integer exit code
Game of life in F#
f#;game of life
You don't need the functions you created to work with arrays. There's no point in putting them in modules like that unless you're going to give the modules the [<RequireQualifiedAccess>] attribute.You also didn't need the Cell type or that operatorYou shouldn't use and to define your types unless they're mutually recursive.open Systemopen System.Texttype Board (width : int, height : int) =    let grid = Array2D.create width height false    let withinBounds (x:int) (y:int) =        (0 <= x  && x < width) && (0 <= y && y < height)    let getNbs x y =        ([| x-1,y+1; x,y+1; x+1,y+1;            x-1,y  ;        x+1,y  ;            x-1,y-1; x,y-1; x+1,y-1 |]         |> Array.filter(fun (a,b) -> (withinBounds a b))         |> Array.filter(fun (a,b) ->  grid.[a,b] = true)).Length    member __.Item        with get (x,y)   = grid.[x,y]        and  set (x,y) v = grid.[x,y] <- v    member __.Tick() =        grid |> Array2D.iteri( fun x y alive ->            let liveNeighbors = getNbs x y            match alive with            | true  -> grid.[x,y] <- liveNeighbors = 2 || liveNeighbors = 3            | false -> grid.[x,y] <- liveNeighbors = 3        )    override __.ToString() =        let frame = Array2D.zeroCreate height width        grid |> Array2D.iteri(fun x y alive ->                match alive with                |true  -> frame.[height-1-y,x] <-[@]                |false -> frame.[height-1-y,x] <-[ ]        )        let sb = StringBuilder()        frame |> Array2D.iteri(fun _ y str ->            match y = height-1 with            | true  -> sb.Append(str).Append(\n) |> ignore            | false -> sb.Append(str) |> ignore        )        sb.ToString()The __.Item method gives you indexed acces into the board like thislet tb = Board(5,5) tb.[1,1] <- truetb.[1,0] <- truetb.[0,1] <- truetb.[0,3] <- truetb.[2,4] <- truetb.[4,4] <- trueprintfn %A tb tb.Tick()printfn %A tbtb.Tick()printfn %A tb[ ][ ][@][ ][@] [@][ ][ ][ ][ ] [ ][ ][ ][ ][ ] [@][@][ ][ ][ ] [ ][@][ ][ ][ ] [ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ] [@][ ][ ][ ][ ] [@][ ][ ][ ][ ] [@][@][ ][ ][ ] [ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ] [@][@][ ][ ][ ] [@][@][ ][ ][ ] There's no need to build and use the console to test this code, write your code in an .fsx and run it in FSI