Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the idiomatic way for an implementation to depend on a partial record type?

Tags:

f#

My intent is to define a module with functions which can operate on all records types which comply with certain assumptions about the keys.

To illustrate, let us have the following code:

> type DBRow = { id: string ; createdAt: System.DateTime } ;;
type DBRow =
  {id: string;
   createdAt: System.DateTime;}

> let logCreationInfo row = printf "Record %s created at %s " row.id (row.createdAt.ToString()) ;;
val logCreationInfo : row:DBRow -> unit

I would like to change the above logCreationInfo to be able to operate on all records which have id: string and createdAt: System.DateTime (and maybe other things).

Coming from typescript's structural typing, I'd have expected this to be trivial, but I am exploring the possibility that there is a more idiomatic way to handle this in F#.

I had attempted to handle this using interfaces, but even if that could work, since F# supports only explicit interfaces, this will not be suitable for types I don't define myself.

like image 666
lorefnon Avatar asked Jan 03 '23 20:01

lorefnon


1 Answers

You could use statically resolved type constraints.

let inline logCreationInfo (x : ^t) =
    printfn "Record %s created at %s" 
        (^t : (member id : string) (x))
        ((^t : (member createdAt : System.DateTime) (x)).ToString())
like image 138
Antti Leppänen Avatar answered Jan 05 '23 09:01

Antti Leppänen