2012-08-06 54 views
15

在C#中,我可以为T类型的通用阵列像这样定义一个扩展方法:如何在F#中定义T []的类型扩展?

,但对我的生活我无法弄清楚如何做到在F#一样!我试过type 'a array with,type array<'a> withtype 'a[] with,编译器对其中的任何一个都不满意。

任何人都可以告诉我什么是在F#中这样做的权利?

当然,我可以通过掩盖Array模块来做到这一点,并很容易地添加一个功能,但我真的想知道如何做到这一点,作为扩展方法!

+0

什么是“为我的生活”意味着:)? – Omu 2012-08-06 21:35:21

+0

扩展'System.Array'是我的第一个想法,但需要一个类型参数和强制转换,除非你可以使用'obj'。 – Daniel 2012-08-06 21:39:37

+1

@Chuck Norris - 意思是'我不能...甚至在我非常努力地尝试' – theburningmonk 2012-08-06 21:42:54

回答

27

你必须使用“反引号标记”写数组类型 - 这样的:

type 'a ``[]`` with 
    member x.GetOrDefault(n) = 
    if x.Length > n then x.[n] 
    else Unchecked.defaultof<'a> 

let arr = [|1; 2; 3|] 
arr.GetOrDefault(1) //2 
arr.GetOrDefault(4) //0 

编辑:语法type ``[]``<'a> with ...似乎也被允许。在F#源文件(prim-types-prelude.fs)中,你可以找到如下定义:

type ``[]``<'T> = (# "!0[]" #) 
+0

+1好找!这是在规格/文档? – Daniel 2012-08-07 16:47:17

+0

@Daniel:试验。我试图找到规范/文档中的任何内容,但没有成功。 – 2012-08-07 16:49:12

+0

对不起,我编辑了我的问题。谢谢。 – Daniel 2012-08-07 16:49:50

10

好问题。我无法弄清楚如何延长'T[]但你可以采取的事实,即阵列实现IList<_>做:

type System.Collections.Generic.IList<'T> with 
    member x.GetOrDefault(n) = 
    if x.Count > n then x.[n] 
    else Unchecked.defaultof<'T> 

let arr = [|1; 2; 3|] 
arr.GetOrDefault(1) //2 
arr.GetOrDefault(4) //0 
+1

我很确定F#中没有合法的语法来向数组类型添加扩展成员,所以这可能是最好的选择我不能想到任何缺点,除了这种方法也出现在任何其他IList类型中)。 – Brian 2012-08-06 21:36:47

+0

@丹尼尔 - 圣洁的废话,你是对的! 'T []确实实施IList <'T>!我不知道!不知道这对我来说是否合理,但是一个数组需要连续的内存块,对吗?因此每次添加操作都必须重新分配给整个新阵列,这在我看来应该是你应该劝阻并鼓励使用List (它有一个内部缓冲区来管理)的东西。 – theburningmonk 2012-08-06 21:40:11

+3

'IList <_>'的变异成员,'Add' /'Remove'等,抛出'NotSupportedException'。尝试:'([| 1 |]:> System.Collections.Generic.IList <_>).Add(2)' – Daniel 2012-08-06 21:44:33

相关问题