2010-11-06 61 views
7

此代码反转的字符串:我可以在F#中使用管道运算符将参数传递给构造函数吗?

let reverse (s : string) = new string(s.ToCharArray() |> Array.rev) 

可以这样使用管道运算符来传递所需参数的构造函数string()被改写?例如,这似乎更地道:

// Doesn't compile: 
let reverse (s : string) = s.ToCharArray() |> Array.rev |> new string 

同样的,我为什么不能使用string运营商通过以下方式?

let reverse2 (s : string) = s.ToCharArray() |> Array.rev |> string 

这是在行动:

> reverse2 "foo" ;; 
val it : string = "System.Char[]" 

它返回类型,而不是 “喝”。

+0

[在对象构造函数中使用F#管道符号](http://stackoverflow.com/questions/531178/using-the-f-pipe-symbol-with-an-object-constructor) – gradbot 2010-11-06 14:21:46

+0

This应该可以在F#4.0中出现:http://blogs.msdn.com/b/fsharpteam/archive/2014/11/12/announcing-a-preview-of-f-4-0-and-the -visual-f-tools-in-vs-2015.aspx – 2015-05-13 12:14:22

回答

9

不,管道运算符只能与F#函数一起使用,它不能用于类构造函数,成员方法或静态方法。原因是这些方法支持的重载会使F#的类型推断复杂化。但是,如果你真的想使用管道,您可以在char数组中的每个元素映射到一个字符串,然后通过管道将序列为Seq.concat ""

s.ToCharArray() |> Array.rev |> Seq.map(string) |> String.concat "" 

或者你可以包装在F#方法的字符串构造函数的调用:

let stringCArrCtor (carr: char[]) = 
    new string(carr) 

s.ToCharArray() |> Array.rev |> stringCArrCtor 

并回答你的最后一个问题,

s.ToCharArray() |> Array.rev |> string 

不能使用,因为它相当于

(s.ToCharArray() |> Array.rev).ToString() 

和Array ToString()方法没有被覆盖,所以它只是返回默认的反射类型名称。

+0

感谢您的回复。看一下'string'运算符的类型签名,你怎么知道它不仅仅是一个带对象并返回字符串的函数?我仍然坚持我的最后一个问题。 – royco 2010-11-06 06:31:30

+1

@Slack,如果将鼠标悬停在字符串函数上,它会告诉你它是一个函数'T - >“,它使用”ToString()“将参数转换为字符串。你也可以看到它是运算符命名空间的一部分,在其中还有其他几个转换函数(如int,long,float,...),编译器会对它进行特殊处理,使它们作为优化的“重载”函数。在源代码中查看prim-types.fs中的第4074-4091行。 – 2010-11-06 13:35:39

9

正如Stephen提到的,最好的办法是定义一个调用构造函数的新函数。你可以把它放到一个名为String的模块中(在你的一些名字空间里),这样你就可以得到和其他F#函数一样的感觉。我可能会使用:

module String = 
    let create (c:char[]) = new string(c) 

使用构造一流的价值观的问题出现在这之前,但我再也找不到我前面的答案 - 有一个很疯狂的把戏,让你的能力,但它是一个巨大的黑客(没有人应该使用它,并且一些F#的下一个版本希望会禁止)。无论如何,你可以使用statically resolved type parameters编写如下:

let inline ctor< ^R, ^T when ^R : 
     (static member ``.ctor`` : ^T -> ^R)> (arg:^T) = 
    (^R : (static member ``.ctor`` : ^T -> ^R) arg) 

而且使用这样的功能:

"ABC".ToCharArray() |> Array.rev |> ctor<string, _>;; 

ctor功能基本要求指定为第一类参数的类型有一个构造函数和它调用构造函数(其他类型参数是构造函数的参数,并由编译器推断)。但这只是一个好奇心 - 定义你自己的功能是最好的方法。

+0

这非常酷。我现在必须开始学习F#了! – leppie 2010-11-06 07:35:50

+0

奇怪的是,“黑客”打破了fsi.exe 3.1: 错误FS3066:无效的成员名称。会员可能没有名字'.ctor'或'.cctor' – larsw 2014-05-30 18:35:52

相关问题