3 people like it.
Like the snippet!
F# SRTP of Type Classes from OO Perspective
Similar to http://fssnip.net/7Tr, this implementation translates the Scala from https://functional.works-hub.com/blog/Type-classes-from-OO-perspective but uses statically resolved type parameters to show how something similar could be done with computation expression instances.
It's really too bad you have to pass an instance of the implementation. It would be nice to be able to specify a module or class with a static member.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
|
open System
type Circle = Circle of radius:double
type Rectangle = Rectangle of width:double * length:double
type CircleShape() =
member this.Area(Circle(radius)) = Math.PI * Math.Pow(radius, 2.)
let circleShape = CircleShape()
type RectangleShape() =
member this.Area(Rectangle(width, length)) = width * length
let rectangleShape = RectangleShape()
let inline areaOf shapeImpl shape =
( ^T : (member Area : 'A -> double) (shapeImpl, shape))
|
namespace System
Multiple items
union case Circle.Circle: radius: double -> Circle
--------------------
type Circle = | Circle of radius: double
Full name: Script.Circle
Multiple items
val double : value:'T -> double (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.double
--------------------
type double = Double
Full name: Microsoft.FSharp.Core.double
Multiple items
union case Rectangle.Rectangle: width: double * length: double -> Rectangle
--------------------
type Rectangle = | Rectangle of width: double * length: double
Full name: Script.Rectangle
Multiple items
type CircleShape =
new : unit -> CircleShape
member Area : Circle -> float
Full name: Script.CircleShape
--------------------
new : unit -> CircleShape
val this : CircleShape
member CircleShape.Area : Circle -> float
Full name: Script.CircleShape.Area
val radius : double
type Math =
static val PI : float
static val E : float
static member Abs : value:sbyte -> sbyte + 6 overloads
static member Acos : d:float -> float
static member Asin : d:float -> float
static member Atan : d:float -> float
static member Atan2 : y:float * x:float -> float
static member BigMul : a:int * b:int -> int64
static member Ceiling : d:decimal -> decimal + 1 overload
static member Cos : d:float -> float
...
Full name: System.Math
field Math.PI = 3.14159265359
Math.Pow(x: float, y: float) : float
val circleShape : CircleShape
Full name: Script.circleShape
Multiple items
type RectangleShape =
new : unit -> RectangleShape
member Area : Rectangle -> double
Full name: Script.RectangleShape
--------------------
new : unit -> RectangleShape
val this : RectangleShape
member RectangleShape.Area : Rectangle -> double
Full name: Script.RectangleShape.Area
val width : double
val length : double
val rectangleShape : RectangleShape
Full name: Script.rectangleShape
val areaOf : shapeImpl:'T -> shape:'A -> double (requires member Area)
Full name: Script.areaOf
val shapeImpl : 'T (requires member Area)
val shape : 'A
More information