Last active
May 18, 2020 18:56
-
-
Save baronfel/58d9699351fc97e2a908a99de60085cf to your computer and use it in GitHub Desktop.
deconstruct tinkering
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Wrapper() = | |
let mutable _one = 0 | |
let mutable _two = 0 | |
member _.one | |
with get () = _one | |
and set (newValue: int) = | |
_one <- newValue | |
member _.two | |
with get () = _two | |
and set (newValue: int) = | |
_two <- newValue | |
/// C#-style deconstructor | |
member this.Deconstruct(one: _ outref, two: _ outref) = | |
one <- this.one | |
two <- this.two | |
// /// this basically does what the F# compiler does for outref 't parameters anyway when you call them: | |
// /// initialize a cell for the value, and pass the address in to the called member | |
// member inline this.Deconstruct() = | |
// let mutable one = Unchecked.defaultof<_> | |
// let mutable two = Unchecked.defaultof<_> | |
// this.Deconstruct(&one, &two) | |
// struct(one, two) | |
let inline de< ^ty, ^inputs, ^outputs when ^ty: (member Deconstruct: ^inputs -> ^outputs) > (w: ^ty) = | |
( ^ty: (member Deconstruct: ^inputs -> ^outputs) (w, Unchecked.defaultof< ^inputs >)) | |
let inline deUnit< ^ty, ^outputs when ^ty: (member Deconstruct: unit -> ^outputs) > (w: ^ty) = | |
( ^ty: (member Deconstruct: unit -> ^outputs) (w)) | |
let w = Wrapper() | |
match w.Deconstruct() with | |
| (one, two) -> printfn "%d %d" one two | |
// match deUnit w with | |
// | (one, two) -> printfn "%d %d" one two | |
// error on the `de` invocation here is: | |
// The member or object constructor 'Deconstruct' takes 2 argument(s) but is here given 1. | |
// The required signature is 'member Wrapper.Deconstruct : one:outref<int> * two:outref<int> -> unit' | |
match de w with | |
| (one, two) -> printfn "%d %d" one two |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// idea of what to do to enable F#+-style inline usage for arbitrary deconstruct overloads | |
type Deconstruct = | |
static member inline Invoke f = | |
let inline call_2 (a: ^a, b: ^b) = ((^a or ^b) : (static member Deconstruct: _*_ -> _) b, a) | |
call_2 (Unchecked.defaultof<Deconstruct>, Unchecked.defaultof<'t>) f | |
static member Deconstruct (deconstructorFn: 'a outref -> unit, _: Deconstruct) = | |
let mutable a = Unchecked.defaultof<'a> | |
deconstructorFn &a | |
a | |
static member Deconstruct (deconstructorFn: 'a outref * 'b outref -> unit, _: Deconstruct) = | |
let mutable a = Unchecked.defaultof<'a> | |
let mutable b = Unchecked.defaultof<'b> | |
deconstructorFn (&a, &b) | |
/// this works at the call-site, but then the deconstructorFn parameters error with: | |
/// The parameter 'deconstructorFn' has an invalid type '(outref<'a> -> unit)'. This is not permitted by the rules of Common IL.F# Compiler(3300) | |
let inline decon (item: 't) = Deconstruct.Invoke item | |
a, b |
yeah :) I've updated the gist with that fix + some further tinkering.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I assume you meant
printfn "%d" d
, right? (sorry, no answers yet on your slack q.)