F#: Best practices for organizing types and modules : <p>If I take the functional approach of defining a type, and then describing functions (as opposed to instance methods) that operate on that type, how should I organize my code?</p>

<p>I generally go one of three ways:</p>

<p>(1):</p>

<pre><code>module MyType =
    type MyType (x : int) =
        member val X = x with get

    let myFunction myType y = myType.X + y
</code></pre>

<p>(2):</p>

<pre><code>type MyType (x : int) =
    member val X = x with get

[&lt;RequireQualifiedAccess&gt;]
module MyTypeOps =
    let myFunction myType y = myType.X + y
</code></pre>

<p>(3):</p>

<pre><code>type MyType =
    {
        x : int
    }

    static member MyFunction myType y = myType.x + y
</code></pre>

<p>Pro of (1) is that functions are defined in a module.  Cons of (1) are that the type is defined in the module, too, resulting in ugly <code>MyType.MyType</code> redundancy on instantiation and the inability to <code>[&lt;RequireQualifiedAccess&gt;]</code> if you want to allow <code>open MyType</code> as a work-around for that redundancy.</p>

<p>Pros of (2) are functions defined in a module, and no module.type redundancy.  Con is that the module cannot be the same name as the type.</p>

<p>Pro of (3) is that the methods are static, and no module.type redundancy.  Cons are that you cannot define some types (e.g. non-method values and active patterns) under this method.</p>

<p>Normally, I prefer (2), even though I hate having to name the module something that's less descriptive and intuitive than it should be.  (2) also allows me to create mutually dependent types using <code>type ... and ...</code> in the rare case that I need to do that, which is obviously impossible for types defined in separate modules like approach (1).</p>

<p>What approach do my fellow F# programmers take?  I'm wondering if I'm overlooking something obvious (or not-so-obvious), or, if I'm not, whether there's a convention out there that addresses the inability to name a module the same name as its corresponding type inside the same namespace.</p>
