在F#中编写这些方法的功能方式

Nic*_*ick 6 f# idiomatic

为了计算方形和圆形的面积,我定义了以下类型:

type Square = {width: float; length: float;} with
    member this.area = this.width * this.length
    member this.perimeter = (this.width + this.length) * 2.

type Circle = {r:float} with 
    member this.area = System.Math.PI * this.r * this.r
    member this.perimeter = 2. * System.Math.PI * this.r

let s1 = {width = 3.; length = 4.}
let c1 = {r = 8.3}

printfn "%A" s1
printfn "The area of s1 is: %A" s1.area
printfn "The perimeter of s1 is: %A" s1.perimeter


printfn "%A" c1
printfn "The area of c1 is: %A" c1.area
printfn "The perimeter of c1 is: %A" c1.perimeter
Run Code Online (Sandbox Code Playgroud)

当我读到这篇文章时:http: //fsharpforfunandprofit.com/posts/type-extensions/

它指出:

  • 方法不适合类型推断
  • 方法不适合高阶函数

所以,请求那些刚接触功能编程的人.如果可以,请不要使用方法,特别是在学习时.它们是一个可以阻止您从函数式编程中获得全部好处的拐杖.

那么解决这个问题的功能方法是什么?或者F#方式是什么?


编辑:

在阅读了"F#组件设计指南"(屈膝于@VB)和@ JacquesB的评论之后,我认为在类型中实现成员方法是最简单的内在方式:

type Square2 (width: float, length: float) =
    member this.area = width * length
    member this.perimeter = (width + length) * 2.
Run Code Online (Sandbox Code Playgroud)

(这是我原来的几乎相同的Square类型-这Square2不仅节省了seveal this.作为前缀this.width,this.length.)

同样,F#组件设计指南非常有用.

svi*_*ick 8

一种更实用的方法是创建一个有Shape区别的联合,其中SquareCircle将是它的情况.然后创建函数areaperimeter,取Shape和使用模式匹配:

type Shape =
    | Square of Width: float * Length: float
    | Circle of R: float

let area = function
    | Square (width, length) -> width * length
    | Circle r -> System.Math.PI * r * r

let perimeter = function
    | Square (width, length) -> (width + length) * 2.
    | Circle r -> 2. * System.Math.PI * r

let s1 = Square(Width = 3., Length = 4.)
let c1 = Circle(R = 8.3)

printfn "%A" s1
printfn "The area of s1 is: %A" (area s1)
printfn "The perimeter of s1 is: %A" (perimeter s1)


printfn "%A" c1
printfn "The area of c1 is: %A" (area c1)
printfn "The perimeter of c1 is: %A" (perimeter c1)
Run Code Online (Sandbox Code Playgroud)

  • 为什么这更具功能性?请详细说明.这两种方法都缺乏副作用. (3认同)