Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static casting between types for Generic nested records

Nested F# Record with generic type parameter, how do I statically cast between types in nested structure equivalent to traversing and performing 'T |> 'K, e.g. float |> int?

Currently I am Naively traversing the nested records and explicitly converting the type with from:float |> to:int or equivalently int(from). However, this is not very beautiful.

type Person<'T> = {Id : int; Value : 'T}
type Family<'T> = {Id : 'T; People : seq<Person<'T>>}

let fam1 = {Id = 1.0; People = [{Id = 1.1; Value = 2.9}; {Id = 1.2; Value = 4.4}]} : Family<float>
let fam2 = {Id = 2.0; People = [{Id = 2.1; Value = 3.9}; {Id = 2.2; Value = 5.4}]} : Family<float>

let partyFloat = seq{ yield fam1; yield fam2}

// In general, how to do this from a type T to a type K where conversion using T |> K will work
let partyInt : seq<Family<int>> = partyFloat

How to statically and/or lazily convert to seq<Family<int>>? In my real world case I have a DiffSharp D type that can be converted to a float with D |> float or float(D).

like image 1000
Pontus Hultkrantz Avatar asked Jun 21 '26 17:06

Pontus Hultkrantz


1 Answers

There is no magic way to cast the insides of types, you have to write your own.

It is idiomatic for F# and functional programming in general (and I personally recommend it, too) to write small functions for simple data transformations, and then assemble them together:

let mapPerson f p = { Id = p.Id; Value = f p.Value }
let mapFamily f fm = { Id = f fm.Id; People = Seq.map (mapPerson f) fm.People }
let mapParty f = Seq.map (mapFamily f)

let partyInt = mapParty int partyFloat

But of course you can do it in one big messy go:

let partyInt = 
    partyFloat
    |> Seq.map (fun fm -> 
        { Id = int fm.Id
          People = 
             fm.People
             |> Seq.map (fun p ->
                 { Id = p.Id; Value = int p.Value }
             )
        }
    )
like image 69
Fyodor Soikin Avatar answered Jun 25 '26 19:06

Fyodor Soikin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!