Reputation: 2254
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.
Upvotes: 3
Views: 613
Reputation: 26174
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.
Upvotes: 4