f#中的重载取消引用(!)和赋值(:=)运算符

Ray*_*Ray 2 f# overloading operator-keyword

我正在尝试重新引用解除引用(!)和赋值(:=)运算符,但不是全局运算符.我仍然希望保持通常的ref op重载.这里有一些代码来说明问题:

type MyVar<'a>(init:'a) =
    let mutable _value = init
    member __.Get() = _value
    member __.Set x = _value <- x
    //static member (!) (s:MyVar<'a>) = s.Get()      // compiles, doesn't work
    //static member (:=) (d:MyVar<'a>, s) = d.Set(s) // warning, doesn't work

//let inline (!) (x :MyVar<'a>) = x.Get()           // overrides !ref
//let inline (:=) (x :MyVar<'a>) (v :'a) = x.Set(v) // overrides ref := v 
let inline (!!) (x :MyVar<'a>) = x.Get()            // works but ugly
let inline (.=) (x :MyVar<'a>) (v :'a) = x.Set(v)   // works ... meh

let test_myvar() =
    let mv = new MyVar<_>("wee")
    let r = ref 100
    let x = !mv
    let y = !!mv
    let z = !r
    mv .= "haaa"
    r := 42
Run Code Online (Sandbox Code Playgroud)

解:

@ Carsten的解决方案正是我所寻找和工作的.然而,事实证明我正在使用Websharper,它使用Quotations进行编译,而@Carstens解决方案变得有点复杂.由于Websharper.UI.Next包含该解决方案,我所需要的只是包含在我的项目中,它的工作原理!

Car*_*ten 5

你可以通过静态约束来实现这一点- 通过重载(!)(:=)运算符来尝试:

type MyVar<'a>(init:'a) =
    let mutable _value = init
    member __.Value with get () = _value and set v = _value <- v

let inline (!) a =
    (^a : (member Value : ^b) a)

let inline (:=) a v =
    (^a : (member Value : ^b with set) (a, v))
Run Code Online (Sandbox Code Playgroud)

我删除了你的访问者,因为我只需要和你一样Ref<'a>(但你可以重新添加它们)

示范

这是一个F#-interactive会话,用你的价值证明这一点:

val mv : MyVar<string>
val r : int ref = {contents = 100;}

> !mv;;
val it : string = "wee"
> !r;;
val it : int = 100
> mv := "It works";;
val it : unit = ()
> !mv;;
val it : string = "It works"
> r := 50;;
val it : unit = ()
> !r;;
val it : int = 50
Run Code Online (Sandbox Code Playgroud)

备注

我不确定我是否真的会这样做 - 你只是重新发明了 - Ref(作为一个班级)并且什么也没有获得,当然这对其他人来说可能很难读 - 所以要小心对待.

  • 如果MyRef具有其他功能,这很有用,例如我们在UI.Next中使用它来实现[反应变量](https://github.com/intellifactory/websharper.ui.next/blob/master/WebSharper.UI.Next/ Notation.fsi). (2认同)