记录的通用方法

时间:2016-01-27 13:09:58

标签: f#

我想知道是否有更好的方法来实现接受记录并修改它们的函数。

所以我有两种类型的实体,都在磁盘上有相应的文件:

0123456789().-

我想要能够复制图片和书籍的通用功能。在OOP世界中,我可能会创建公共接口type Picture = { Artist : string; File : string } type Book = { Author : string; File : string } ,在两个记录中实现它,然后创建适用于它的Move方法。类似的东西:

IArtefact { File : string }

但是我认为F#不支持这样的概念。 F#的方式是什么?

2 个答案:

答案 0 :(得分:4)

这是可能的,为什么不是;)

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

编辑:如果您想处理更新:

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

答案 1 :(得分:2)

虽然没有通用的更改复制记录方法,但有一个用于移动任何具有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#" }

然后可以扩展它以移动任何知道如何移动的东西:

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#"