I am trying to build a generic function to manipulate a record my code looks like:
type Status = Active | Inactive
type IStatus =
abstract member Status: Status
type User =
{
Username : string;
Status : Status
}
interface IStatus with
member x.Status = x.Status
let ChangeStatus<'T when 'T :> IStatus> newStatus (t:'T) =
{t with Status = newStatus}
Now I get the following error:
expression was expected to have type
'T
but here has type
User
Obviously I just want to create a type constraint for Records which implement IStatus. Am I thinking too OO? Or is there merit to this approach and how do I create this ChangeStatus function?
Thank you for reading.
I don't think it's possible what you're trying to do, because it would need a "generic record cloner" I mean a generic record expression and that's not supported at the moment.
You can create a clone method for each subclass, that should work but you will have to repeat the code to clone the record. It might be a generic solution but involving reflection.
However if you change your design you can get the desired functionality. For instance you can use a generic nested record:
type Status = Active | Inactive
type StatusRecord<'T> =
{
Item : 'T
Status : Status
}
let changeStatus newStatus t = {t with Status = newStatus}
// TEST
type User = {Username : string}
type Group = {Groupname : string; members : User list}
let user = {Status = Active; Item = {Username = "User1"}}
let group = {Status = Active; Item = {Groupname = "Group1"; members = []}}
This is a very lightweight solution, you will write less code but it will change your design which depending on the rest of your code will make sense or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With