7 people like it.
Like the snippet!
Implement interface by expression
What feature would I like to see in F#? One thing is the ability to implement an interface in a class by delegating the implementation to an expression. This snippet demonstrates the idea using a simple example of vectors.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
|
open System
// Let's say we have an interface representing vectors
// (in reality this would have quite a few members)
type IVector =
abstract Data : seq<float>
abstract GetValue : int -> float
// Now, we have a concrete vector implementation using an array
type ArrayVector(data:float[]) =
interface IVector with
member x.Data = data |> Seq.ofArray
member x.GetValue(i) = data.[i]
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
|
// And we want to create a "lazy" vector that loads the data
// from database. It has range of values and other operations
// can check for 'DatabaseVector' and instead of actually working
// with in-memory data, they can just adjust min/max date...
//
// When we actually access the data of the vector, this needs
// to load the data from the database and redirect all operations
// to an actual in-memory vector
type DatabaseVector(min:DateTime, max:DateTime) =
let vector = Lazy.Create(fun () ->
let count = int (max - min).TotalDays
let data = [| for i in 0 .. count - 1 -> 3.0 |]
ArrayVector(data) :> IVector)
// Now we have to implement the interface by writing
// all the members and just making calls to 'vector' :-((
interface IVector with
member x.Data = vector.Value.Data
member x.GetValue(i) = vector.Value.GetValue(i)
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
|
type DatabaseVector(min:DateTime, max:DateTime) =
let vector = Lazy.Create(fun () ->
let count = int (max - min).TotalDays
let data = [| for i in 0 .. count - 1 -> 3.0 |]
ArrayVector(data) :> IVector)
// I would like to be able to say "implement this interface"
// by delegating all the operations to the object returned by
// an expression <expr>. In this example, the expression is just
// 'vector.Value' (but you can imagine other functions to implement
// common interfaces like IDisposable, etc...)
interface IVector = vector.Value
|
namespace System
namespace Microsoft.FSharp.Data
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = System.Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
module Seq
from Microsoft.FSharp.Collections
val ofArray : source:'T [] -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.ofArray
val min : e1:'T -> e2:'T -> 'T (requires comparison)
Full name: Microsoft.FSharp.Core.Operators.min
val max : e1:'T -> e2:'T -> 'T (requires comparison)
Full name: Microsoft.FSharp.Core.Operators.max
Multiple items
active recognizer Lazy: Lazy<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.( |Lazy| )
--------------------
type Lazy<'T> = System.Lazy<'T>
Full name: Microsoft.FSharp.Control.Lazy<_>
static member System.Lazy.Create : creator:(unit -> 'T) -> System.Lazy<'T>
More information