F# 超载+;F中的运算符#
所以我有这个:F# 超载+;F中的运算符#,f#,operator-overloading,F#,Operator Overloading,所以我有这个: open System open System.Linq open Microsoft.FSharp.Collections type Microsoft.FSharp.Collections.List<'a> with static member (+) (First : List<'a>) (Second : List<'a>) = First.Concat(Second) let a = [1; 2; 3; 4;
open System
open System.Linq
open Microsoft.FSharp.Collections
type Microsoft.FSharp.Collections.List<'a> with
static member (+) (First : List<'a>) (Second : List<'a>) =
First.Concat(Second)
let a = [1; 2; 3; 4; 54; 9]
let b = [3; 5; 6; 4; 54]
for x in List.(+) a b do
Console.WriteLine(x)
但这样做给了我一个机会
The type 'int list' does not support any operands named '+'
网络上的文档和示例都是不完整的,尽管我使用了google fu,但我还是无法让它正常工作。基本上,我来自python的背景,我想让我的列表操作语法像我习惯的那样简洁:它不需要超过1个字符的中缀符号 首先,重写运算符应该以元组形式声明,而不是以携带形式声明。就你而言:
type Microsoft.FSharp.Collections.List<'a> with
static member (+) (first: List<'a>, second: List<'a>) =
first.Concat(second)
键入Microsoft.FSharp.Collections.List,第二个:List我认为使用扩展方法重载运算符不起作用。您可以使用以下命令定义列表(+)的全局运算符重载:
let inline(+)(f:List)=f.Concat(s)
请注意,@
已经是concat列表的1字符中缀运算符。正如其他答案所指出的,您不能将+
的实现添加到现有类型,因为扩展成员被忽略,而独立的让绑定隐藏默认(重载)实现
如果您想使用+
(实际上并不需要,因为F#library包含运算符@
),则必须为直接支持运算符的F#list编写包装器:
open System.Collections
open System.Collections.Generic
/// Wrapper for F# list that exposes '+' operator and
/// implements 'IEnumerable<_>' in order to work with 'for'
type PlusList<'T>(list : list<'T>) =
member x.List = list
static member (+) (first : PlusList<'a>, second : PlusList<'a>) =
first.List @ second.List
interface IEnumerable with
member x.GetEnumerator() = (list :> IEnumerable).GetEnumerator()
interface IEnumerable<'T> with
member x.GetEnumerator() = (list :> IEnumerable<_>).GetEnumerator()
// Simple function to wrap list
let pl l = PlusList<_>(l)
let a = pl [1; 2; 3; 4; 54; 9]
let b = pl [3; 5; 6; 4; 54]
for x in a + b do
System.Console.WriteLine(x)
opensystem.Collections
open System.Collections.Generic
///公开“+”运算符和
///实现“IEnumerable”以便使用“for”
类型(PlusList)=
成员x.列表=列表
静态成员(+)(第一个:PlusList)=
first.List@second.List
接口IEnumerable with
成员x.GetEnumerator()=(列表:>IEnumerable).GetEnumerator()
接口IEnumerable实际上,有一种方法可以使用静态约束和重载“重新连接”现有运算符
type ListExtension = ListExtension with
static member (?<-) (ListExtension, a , b) = a @ b
static member inline (?<-) (ListExtension, a , b) = a + b
let inline (+) a b = (?<-) ListExtension a b
// test
let lst = [1;2] + [3;4]
// val lst : int list = [1; 2; 3; 4]
let sum = 1 + 2 + 3 + 4
// val sum : int = 10
这不会破坏现有的数值类型的(+)
。它可以工作,但它会覆盖任何类型的所有(+)运算符。所以你不能再调用2+3来表示整数了。这与运算符重载的想法背道而驰。。你是对的。。。奇怪的是,F#编译器没有使用用于确定要使用的正确运算符的值的类型。这是否意味着F#不允许您用多个签名重载一个方法,然后在每个使用点(a.l.a.Java)选择正确的一个?此限制仅适用于let绑定函数。你仍然可以用通常的方式重载成员函数。哦,我不知道。谢谢@但是有一种方法可以绕过这个限制,看看我的答案。
open System.Collections
open System.Collections.Generic
/// Wrapper for F# list that exposes '+' operator and
/// implements 'IEnumerable<_>' in order to work with 'for'
type PlusList<'T>(list : list<'T>) =
member x.List = list
static member (+) (first : PlusList<'a>, second : PlusList<'a>) =
first.List @ second.List
interface IEnumerable with
member x.GetEnumerator() = (list :> IEnumerable).GetEnumerator()
interface IEnumerable<'T> with
member x.GetEnumerator() = (list :> IEnumerable<_>).GetEnumerator()
// Simple function to wrap list
let pl l = PlusList<_>(l)
let a = pl [1; 2; 3; 4; 54; 9]
let b = pl [3; 5; 6; 4; 54]
for x in a + b do
System.Console.WriteLine(x)
type ListExtension = ListExtension with
static member (?<-) (ListExtension, a , b) = a @ b
static member inline (?<-) (ListExtension, a , b) = a + b
let inline (+) a b = (?<-) ListExtension a b
// test
let lst = [1;2] + [3;4]
// val lst : int list = [1; 2; 3; 4]
let sum = 1 + 2 + 3 + 4
// val sum : int = 10
for x in (+) a b do
Console.WriteLine(x)