Copy and update a record using common types

I have two types, and they have one named value.

type Type1 = 
    {
        p1: int;
        p2: int;
    } 
type Type2 = 
    {
        p1 : int;
        p3 : int;
    }

Is it possible to create a function that changes only this named value (p1) and returns a new record?

I tried and got this far:

type IType = 
    abstract member p1: int;

type Type1 = 
    {
        p1: int;
        p2: int;
    } 
    interface IType with
        member this.p1 = this.p1

type Type2 = 
    {
        p1 : int;
        p3 : int;
    }
    interface IType with
        member this.p1 = this.p1

let changeP1ToTen (value: 'a when 'a :> IType) = 
    let newValue = {value with p1 = 10}
    newValue

let type1 = 
    {
        p1 = 50
        p2 = 80
    }
let newType1 = 
    changeP1ToTen(type1)

This does not work, since the compiler assumes that the {value with p1 = 10} is Type2, when it can be.

If there is a better and clever solution, this will also help.

I know this is possible if I use mutable for my types or use a class instead of a simple notation, but I was wondering if there is a better way to deal with it and not with the OO approach.

+6
source share
1 answer

I mean, you could try this ...

type Type1 =
    {
        p1 : int;
        p2 : int;
    }
type Type2 =
    {
        p1 : int;
        p2 : int;
    }
type Wrapper =
    | TOne of Type1
    | TTwo of Type2

let changeP1ToTen = function
    | TOne of t1 -> { t1 with p1 = 10 }
    | TTwo of t2 -> { t2 with p1 = 10 }

let type1 = { p1 = 50; p2 = 80 }

// Requires extra wrapping step, is that a dealbreaker?
let newtype1 = TOne type1 |> changeP1ToTen

// If that a problem for ya, here a function to fix it
let iTypeToWrapper (value: 'a when 'a :> IType) =
    match value with
        | :? Type1 as t1 -> TOne t1
        | :? Type2 as t2 -> TTwo t2

let othernewtype1 = iTypeToWrapper type1 |> changeP1ToTen

iTypeToWrapper , , - , Type1 Type2. , , .

// val iTypeToWrapper : ('a when 'a :> IType) -> Wrapper option
let iTypeToWrapper (value: 'a when 'a :> IType) =
    match value with
        | :? Type1 as t1 -> TOne t1 |> Some
        | :? Type2 as t2 -> TTwo t2 |> Some
        | _ -> None
0

All Articles