Skip to content

Instantly share code, notes, and snippets.

@En3Tho
Last active January 23, 2023 17:26
Show Gist options
  • Save En3Tho/a5b9abc62ce0b5ca266980e1615fff2c to your computer and use it in GitHub Desktop.
Save En3Tho/a5b9abc62ce0b5ca266980e1615fff2c to your computer and use it in GitHub Desktop.
#nowarn "3535"
open System.Numerics
module rec Arrays =
type IArray<'T> =
abstract Item: int -> 'T with get
type IOperation<'T> =
static abstract Invoke: 'T * 'T -> 'T
type [<Struct>] PlusOperation<'T when 'T :> INumber<'T>> =
interface IOperation<'T> with
static member Invoke(left, right) = left + right
type [<Struct>] MinusOperation<'T when 'T :> INumber<'T>> =
interface IOperation<'T> with
static member Invoke(left, right) = left - right
type [<Struct>] MultiplyOperation<'T when 'T :> INumber<'T>> =
interface IOperation<'T> with
static member Invoke(left, right) = left * right
type [<Struct>] DivideOperation<'T when 'T :> INumber<'T>> =
interface IOperation<'T> with
static member Invoke(left, right) = left / right
type [<Struct>] Template<'T, 'L, 'R, 'O
when 'T :> INumber<'T>
and 'L :> IArray<'T>
and 'R :> IArray<'T>
and 'O :> IOperation<'T>>(left: 'L, right: 'R) =
static member (+)<'LL, 'RR when 'LL :> IArray<'T> and 'RR :> IArray<'T>>(left: 'LL, right: 'RR) = Template<_, _, _, PlusOperation<'T>>(left, right)
static member (-)<'LL, 'RR when 'LL :> IArray<'T> and 'RR :> IArray<'T>>(left: 'LL, right: 'RR) = Template<_, _, _, MinusOperation<'T>>(left, right)
static member (*)<'LL, 'RR when 'LL :> IArray<'T> and 'RR :> IArray<'T>>(left: 'LL, right: 'RR) = Template<_, _, _, MultiplyOperation<'T>>(left, right)
static member (/)<'LL, 'RR when 'LL :> IArray<'T> and 'RR :> IArray<'T>>(left: 'LL, right: 'RR) = Template<_, _, _, DivideOperation<'T>>(left, right)
member this.Item with get(idx) = 'O.Invoke(left[idx], right[idx])
interface IArray<'T> with
member this.Item with get(idx) = this.Item(idx)
type [<Struct>] Arr<'T when 'T :> INumber<'T>>(data: 'T[]) =
static member op_Implicit(data: 'T[]) = Arr(data)
static member (+)(left: Arr<'T>, right: Arr<'T>) = Template<_, _, _, PlusOperation<'T>>(left, right)
static member (-)(left: Arr<'T>, right: Arr<'T>) = Template<_, _, _, MinusOperation<'T>>(left, right)
static member (*)(left: Arr<'T>, right: Arr<'T>) = Template<_, _, _, MultiplyOperation<'T>>(left, right)
static member (/)(left: Arr<'T>, right: Arr<'T>) = Template<_, _, _, DivideOperation<'T>>(left, right)
member this.Item with get(idx) = data[idx]
interface IArray<'T> with
member this.Item with get(idx) = this.Item(idx)
open Arrays
[<EntryPoint>]
let main argv =
let a = Arr([| 1; 2 |])
let b = Arr([| 3; 4 |])
let c = Arr([| 5; 6 |])
let z = a + b * a * c
let res = [| z[0]; z[1] |] // 16, 50
res |> printfn "%A"
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment