在 f# 中重载解引用 (!) 和赋值 (:=) 运算符
overload dereference (!) and assignment (:=) operators in f#
我试图重载取消引用 (!) 和赋值 (:=) 运算符,但不是全局重载。我仍然想保留通常的 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
解法:
@Carsten 的解决方案正是我一直在寻找和工作的。但是,事实证明我使用的是 Websharper,它使用 Quotations 和 @Carstens 解决方案进行编译,变得有点 more complex。由于 Websharper.UI.Next 包含该解决方案,我所要做的就是将其包含在我的项目中,并且它有效!
你可以让它与 static constraints 一起工作 - 通过在你尝试时重载 (!)
和 (:=)
运算符:
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))
我删除了您的访问器,因为我只需要与 Ref<'a>
相同的访问器(但您可以重新添加它们)
示范[=27=]
这是一个 F# 交互式会话,用您的值演示了这一点:
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
备注
虽然我不确定我是否真的会这样做 - 你只是重新发明了 Ref
-cell(作为 class)并且一无所获,当然它可能难以阅读对于其他人 - 所以要小心对待。
我试图重载取消引用 (!) 和赋值 (:=) 运算符,但不是全局重载。我仍然想保留通常的 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
解法:
@Carsten 的解决方案正是我一直在寻找和工作的。但是,事实证明我使用的是 Websharper,它使用 Quotations 和 @Carstens 解决方案进行编译,变得有点 more complex。由于 Websharper.UI.Next 包含该解决方案,我所要做的就是将其包含在我的项目中,并且它有效!
你可以让它与 static constraints 一起工作 - 通过在你尝试时重载 (!)
和 (:=)
运算符:
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))
我删除了您的访问器,因为我只需要与 Ref<'a>
相同的访问器(但您可以重新添加它们)
示范[=27=]
这是一个 F# 交互式会话,用您的值演示了这一点:
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
备注
虽然我不确定我是否真的会这样做 - 你只是重新发明了 Ref
-cell(作为 class)并且一无所获,当然它可能难以阅读对于其他人 - 所以要小心对待。