Reputation: 13562
I wonder if there is a better way of implementing a function that accepts records and modify them.
So I have entities of two types, both have corresponding files on the disk:
type Picture = { Artist : string; File : string }
type Book = { Author : string; File : string }
I want generic function that can copy both pictures and books. In the OOP world I would probably create common interface IArtefact { File : string }
, implement it in both records and then create Move method that works on it. Something like:
let move<'a:IArtefact>(a : 'a) (path : string) =
File.Move(a.File, path)
{ a with File = path }
However I suppose that F# does not support such concept. What is the F# way of doing so?
Upvotes: 2
Views: 447
Reputation: 13577
This is possible, why wouldn't it be ;)
type IArtefact =
abstract File: string
type Picture =
{ Artist : string; File : string }
interface IArtefact with
member this.File = this.File
let p = { Artist = "test"; File = "test2" }
(p :> IArtefact).File
Edit: If you want to handle updates:
type IArtefact =
abstract File: string
abstract WithFile: string -> IArtefact
type Picture =
{ Artist : string; File : string }
interface IArtefact with
member this.File = this.File
member this.WithFile(file) = { this with File = file } :> IArtefact
Upvotes: 4
Reputation: 8551
While there is no generic way of change-copying records, there is one for moving anything that has a File
:
let inline move from where : string =
let oldFile = (^T : (member File : string) from)
do() // move here
where
type Picture = { Artist: string; File: string }
type Book = { Author: string; File: string }
let p = { Artist = "Vincent van Gogh"; File = "Rooftops" }
let p' = { p with File = move p "The Potato Eaters" }
let b = { Author = "Don Syme"; File = "Generics in CLR" }
let b' = { b with File = move b "Expert F#" }
This could then be expanded to move anything that knows how to be moved:
let inline move' a where =
let oldFile = (^T : (member File : string) a)
do() // move here
(^T: (member moved : string -> ^T) a, where)
type Picture' =
{ Artist: string; File: string } with
member this.moved where = { this with File = where }
type Book' =
{ Author: string; File: string } with
member this.moved where = { this with File = where }
let p2 = { Artist = "Vincent van Gogh"; File = "Rooftops" }
let p2' = move' p2 "The Potato Eaters"
let b2 = { Author = "Don Syme"; File = "Generics in CLR" }
let b2' = move' b2 "Expert F#"
Upvotes: 2