Is it good practice to mix members with module functions when working with classes?

For instance, in this (very simple example) code I have a member in the class, and a module, which both deal with the same type:

open System 

type Thingy(parameter: int) = 
    member val Parameter = parameter 
    override this.ToString() = 
        this.Parameter 
        |> string 

module Thingy = 
    let asBackwardsString thingy = 
        thingy.ToString() 
        |> Seq.rev 
        |> String.Concat 

let value = Thingy(1234) 
let str = value.ToString()
let back = value |> Thingy.asBackwardsString

Is it ‘reasonable’ to do this or should I normally keep to one or the other.

I’m guessing that it’s probably a case-by-case-basis thing but was wondering if there were any major potential pitfalls that I would need to keep an eye out for.

Note 1: (I think) I need to create a class in the first place because the real type is implementing the IEquatable and IComparable interfaces.

Note 2: Also, the code will only be accessed from other F# code so there aren’t any interop requirements.

There aren’t large pitfalls but you may as well reduce the number of structural elements by putting things in one place. A straightforward conversion would be to a static member. You can also do a regular instance member which is often easier to find and nicer to use, and also avoids the risk of writing an argument thingy without a type annotation (which has happened in the code snippet above and resulted in an inferred type 'a not identical with the intended one Thingy).

That seems like good advice to me.

Do it one way or the other, but not both at the same time for the same thing.

As it happens I’ve realised that, in my actual case, I can use a basic record and use the in-built equality and comparison functions so I don’t need the extra complexity of using the interfaces, which is how I got to this, but it’s good to know anyway.

Thanks.