这是类似C#问题的毫不掩饰的尝试.
那么你最喜欢的F#隐藏(或不是)功能是什么?
到目前为止,我使用的大部分功能并没有完全隐藏,但却非常令人耳目一新.就像C#或VB.NET相比,重载运算符是多么微不足道.
并Async<T>帮助我削减了一些真正丑陋的代码.
我对这种语言还很陌生,所以了解野外使用的其他功能会很棒.
我正在尝试定义一个函数,factorize,它使用类似于Seq.sum的结构类型约束(需要静态成员Zero,One,+和/),以便它可以与int,long,bigint等一起使用.I似乎无法获得正确的语法,并且无法在该主题上找到很多资源.这就是我所拥有的,请帮助.
let inline factorize (n:^NUM) =
^NUM : (static member get_Zero: unit->(^NUM))
^NUM : (static member get_One: unit->(^NUM))
let rec factorize (n:^NUM) (j:^NUM) (flist: ^NUM list) =
if n = ^NUM.One then flist
elif n % j = ^NUM.Zero then factorize (n/j) (^NUM.One + ^NUM.One) (j::flist)
else factorize n (j + ^NUM.One) (flist)
factorize n (^NUM.One + ^NUM.One) []
Run Code Online (Sandbox Code Playgroud) 我刚刚了解到OCAML必须有一个.用于执行浮点运算的后缀.一个例子是3. +. 4.equals 7.(float).但是,F#以相同的方式处理浮点和整数运算,因此3 + 4(int)和3. + 4.(float)都有效.
F#+自然分配给int,因此let add a b = a + b属于类型int -> int -> int.确实(+)给了我val it : (int -> int -> int) = <fun:it@6-1>.
这导致了以下序列,我认为这非常违反直觉:
> 3. + 4.;;
val it : float = 7.0
> (+);;
val it : (int -> int -> int) = <fun:it@8-2>
Run Code Online (Sandbox Code Playgroud)
所以我的问题是: "重载"是否由编译器中的特殊机制/案例完成,或者这是一个语言范围的事情所以我可能可以定义一个名为add(或其他任何)的函数,它具有一个整数和一个定义浮子(或任何其他类型).
注意:我最后添加了很多Of interest评论.这些并不是在暗示一个人应该使用inline和static type parameters 威利愿意不愿意,他们有这么一个没有花时间搜索大量的SO与此相关的问题,以更好地理解这些概念的问题.
我知道当需要使函数通用并且需要零(0)值时,F#提供GenericZero.
解析为任何原始数字类型的零值或具有名为Zero的静态成员的任何类型.
所以这让我相信使用GenericZero字符串类型我只需要添加一个名为Zero的静态成员.
由于System.String是.Net框架的一部分,修改.Net源代码不是应该做的.但是,F#提供了Type Extensions.
类型扩展允许您将新成员添加到先前定义的对象类型.
此外,F#提供了String模块,但缺少GenericZero.
有关创建类型扩展的好教程,请参阅:将函数附加到类型.
我测试的代码:
这是在一个名为的项目中 Library1
namespace Extension.Test
module Extensions =
type System.String with
static member Something = "a"
static member StaticProp
with get() = "b"
static member Zero
with get() = "c"
Run Code Online (Sandbox Code Playgroud)
这是在一个名为的项目中 Workspace
namespace Extension.Test
module main =
open Extensions
[<EntryPoint>]
let main argv =
let stringSomething = System.String.Something
printfn …Run Code Online (Sandbox Code Playgroud) generics extension-methods f# type-inference generic-constraints
可能是一个愚蠢的问题,但我刚开始使用F#而且我遇到了一些问题.
说我有这样的功能:
let multiplyByTwo x = x * 2
Run Code Online (Sandbox Code Playgroud)
当我这样称呼时:
let result = multiplyByTwo 5
Run Code Online (Sandbox Code Playgroud)
一切都好,结果是10.
当我这样称呼时:
let result = multiplyByTwo 2.5
Run Code Online (Sandbox Code Playgroud)
我希望得到5或5.0.但实际结果如下:
let result = multiplyByTwo 2.5 ;;
--------------------------------- ^^^stdin(4,28):错误FS0001:此表达式应该具有类型
Run Code Online (Sandbox Code Playgroud)int但这里有类型
Run Code Online (Sandbox Code Playgroud)float
因为我希望这个函数有点通用(即接受浮点数和整数),我不喜欢这个.我的问题当然是:如何解决这个问题?
编写函数的最佳方法是什么,以便它们可以无缝地处理:
我特别需要编写函数,例如计算时间序列的平均值/方差/随机变换,我想只编写这些函数的1个版本.
基于这个问题的讨论,任何人都可以提供代码或代码链接,显示NumericLiteralX模块的完整实现(例如这个)吗?我特别感兴趣的是有效实现FromInt32/ 64用于NumericLiteralX促进通用数字运算的模块.这是从上述问题中得出的可能效率低下的实现:
module NumericLiteralG =
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
let inline FromInt32 (n:int) =
let one : ^a = FromOne()
let zero : ^a = FromZero()
let n_incr = if n > 0 then 1 else -1
let g_incr = if n > 0 then one else (zero - one)
let rec loop i g =
if i = n then g
else …Run Code Online (Sandbox Code Playgroud) 我在F#中编写了一个提供一些按位操作的库¹,我想确保尽可能多的函数是inline使用静态类型参数进行绑定(这允许我编写一个函数并将其用于int16,int32也许甚至bignum只有很少的开销).这条路线肯定无法在某些时候起作用.所述库提供的一些功能有些复杂.
¹注意:我知道通过公共接口公开内联let绑定的问题.
但是,我想把它延伸到最远的程度.现在,我正在尝试以这种形式编写人口计数算法,我正面临一个问题.我不确定如何对掩码进行编码,例如0x3333...,这些算法中出现的掩码.我可以使用一些额外的技巧来绕过移位常数和类似的东西.
有没有我可以使用的技巧,无论是通过F#的类型推断和静态类型参数,还是通过bit-twiddling,以我想要的方式编写算法?有没有什么办法可以在静态泛型函数中编码这些常量?
一个更模糊的问题:我是否可以依赖一些特定的东西来充分利用静态类型参数,尤其是在数值的背景下?例如,我大量使用GenericOne和GenericZero.还有更多这样的事情,我可能错过了吗?
I was trying to put both int and float into a list construction:
> let l2=[1;2.0];;
let l2=[1;2.0];;
----------^^^
stdin(50,11): error FS0001: This expression was expected to have type
int
but here has type
float
>
Run Code Online (Sandbox Code Playgroud)
好吧,如果我在Haskell中写l3 = [1,2.0],它可以构建列表以包含所有"小数"元素.为什么F#不支持自动类型推断?F#基于.net,Int和Float都是Object类型,对吧?为什么Int和Float无法放入一个列表中,而某些元素会自动进行类型提升或转换?似乎F#的类型系统使编写更多通用程序变得非常困难.
任何提示?