Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# F中的函数模板#_F#_Inline - Fatal编程技术网

F# F中的函数模板#

F# F中的函数模板#,f#,inline,F#,Inline,假设我正在解决一个特定的问题,并提出了一个函数 let function parameter1 ... = a lot of adding, multiplying & so on with a lot of literals all over the place 现在,如果我的参数是int类型,那么这个函数可以正常工作。但是在某些地方,我需要它上升到11,我需要额外的推力进入int64甚至biginger。那我该怎么办? 我复制并粘贴函数,更改名称,并查找所有

假设我正在解决一个特定的问题,并提出了一个函数

let function parameter1 ... = 
     a lot of adding, multiplying & so on with a lot of 
     literals all over the place
现在,如果我的参数是int类型,那么这个函数可以正常工作。但是在某些地方,我需要它上升到11,我需要额外的推力进入int64甚至biginger。那我该怎么办? 我复制并粘贴函数,更改名称,并查找所有让编译器认为函数应该在int上运行的文字外观。这太糟糕了

有没有办法做到这一点:

let greatFunction param1 param2 = (param1+1)/(param2*2)
其中param1和param2可以是整数类型的任意组合

编辑:

在下面kvb的一个很棒的技巧上进行了一些扩展,我得出了以下结论

module NumericLiteralG 

  let inline FromZero() = LanguagePrimitives.GenericZero
  let inline FromOne() = LanguagePrimitives.GenericOne
  let inline FromInt32 n =
    let rec loop nIn nOut = 
        if nIn>0 then loop (nIn - 1) (nOut + LanguagePrimitives.GenericOne)
        else nOut
    loop n LanguagePrimitives.GenericZero
所以用起来就不那么难看了

let inline halfSquare num =
   let res = num / 2G
   res * res

let solve1 = halfSquare 5I 
let solve2 = halfSquare 5.0
let solve3 = halfSquare 5uy
现在的问题是我应该用这个吗?如果没有,为什么不呢?

这是我的建议。通常,您有两种选择:

  • 静态成员约束
  • 全局数字关联(在F#PowerPack中提供)
…或者您可以将这些技术结合起来

在您的情况下,听起来静态约束将起作用

该文章中的一个简单示例:

let inline halfSquare num =
   let res = LanguagePrimitives.DivideByInt num 2
   res * res

一种方法是将
内联
关键字和来自模块的通用位组合在一起:


虽然不是很理想,而且有点绕过了主要问题,但您可以添加类型注释来迫使编译器:

let greatFunction (param1:int64) (param2:int64) : int64 = (param1+1)/(param2*2)

当然,F#中没有隐式转换,所以您需要将
L
添加到所有数字文本中,但它们至少会显示为编译器错误。

我认为泛型算术是.NET语言中常见的问题。 有许多文章解释了不同的方法,很快我将发布另一篇文章来解释我的方法,这与您发布的解决方案类似

现在,如果你问我是否应该使用它,我会说:只要你明白你在做什么,为什么不呢?我在生产中部分使用它,完全没有问题,但因为我关心运行时性能,所以我在编译时使用重载来解决所有问题。 然后为了加快编译速度,我重新定义了基本的数学运算符,使其在同一类型中进行操作,否则类型签名会变得非常复杂,编译可能需要很长时间

有更多的事情要考虑,但是对于你的特定问题,这里有一个示例代码:

open System.Numerics

type FromInt = FromInt with
    static member ($) (FromInt, _:sbyte     ) = fun (x:int) -> sbyte      x
    static member ($) (FromInt, _:int16     ) = fun (x:int) -> int16      x
    static member ($) (FromInt, _:int32     ) = id
    static member ($) (FromInt, _:float     ) = fun (x:int) -> float      x
    static member ($) (FromInt, _:float32   ) = fun (x:int) -> float32    x
    static member ($) (FromInt, _:int64     ) = fun (x:int) -> int64      x
    static member ($) (FromInt, _:nativeint ) = fun (x:int) -> nativeint  x
    static member ($) (FromInt, _:byte      ) = fun (x:int) -> byte       x
    static member ($) (FromInt, _:uint16    ) = fun (x:int) -> uint16     x
    static member ($) (FromInt, _:char      ) = fun (x:int) -> char       x
    static member ($) (FromInt, _:uint32    ) = fun (x:int) -> uint32     x
    static member ($) (FromInt, _:uint64    ) = fun (x:int) -> uint64     x
    static member ($) (FromInt, _:unativeint) = fun (x:int) -> unativeint x
    static member ($) (FromInt, _:bigint    ) = fun (x:int) -> bigint     x
    static member ($) (FromInt, _:decimal   ) = fun (x:int) -> decimal    x
    static member ($) (FromInt, _:Complex   ) = fun (x:int) -> Complex(float x,0.0)  

let inline fromInt (a:int) : ^t = (FromInt  $  Unchecked.defaultof< ^t>) a

module NumericLiteralG =
    let inline FromZero() =LanguagePrimitives.GenericZero
    let inline FromOne() = LanguagePrimitives.GenericOne
    let inline FromInt32 (i:int)     = fromInt i


// This will reduce the number of types inferred, will reduce compile time too.
let inline (+) (a:^t) (b:^t) : ^t = a + b
let inline (-) (a:^t) (b:^t) : ^t = a - b
let inline (*) (a:^t) (b:^t) : ^t = a * b
let inline (/) (a:^t) (b:^t) : ^t = a / b
let inline (~-) (a:^t) : ^t = -a


let inline halfSquare num =
   let res = num / 2G
   res * res

let solve1 = halfSquare 5I 
let solve2 = halfSquare 5.0
let solve3 = halfSquare 5uy 

// Define more generic math functions.
opensystem.Numerics
键入FromInt=FromInt,并使用
静态成员($)(FromInt,U2;:sbyte)=乐趣(x:int)->sbyte x
静态成员($)(FromInt,U3;:int16)=乐趣(x:int)->int16x
静态成员($)(FromInt,\uInt32)=id
静态成员($)(FromInt,U3;:float)=fun(x:int)->float x
静态成员($)(FromInt,U3;:float32)=fun(x:int)->float32 x
静态成员($)(FromInt,U3;:int64)=乐趣(x:int)->int64 x
静态成员($)(FromInt,U9:nativeint)=乐趣(x:int)->nativeint x
静态成员($)(FromInt,U3:byte)=乐趣(x:int)->字节x
静态成员($)(FromInt,U3;:uint16)=fun(x:int)->uint16 x
静态成员($)(FromInt,U3;:char)=fun(x:int)->char x
静态成员($)(FromInt,U3;:uint32)=fun(x:int)->uint32 x
静态成员($)(FromInt,U3;:uint64)=fun(x:int)->uint64 x
静态成员($)(FromInt,U3:unativeint)=乐趣(x:int)->unativeint x
静态成员($)(FromInt,U3;:bigint)=乐趣(x:int)->bigint x
静态成员($)(FromInt,U3:decimal)=乐趣(x:int)->十进制x
静态成员($)(FromInt,U3;:复数)=fun(x:int)->Complex(float x,0.0)
让内联fromInt(a:int):^t=(fromInt$未选中。默认值<^t>)a
数字文字模块=
让内联FromZero()=LanguagePrimitives.GenericZero
让内联FromOne()=LanguagePrimitives.GenericOne
让内联FromInt32(i:int)=fromInt i
//这将减少推断类型的数量,也将减少编译时间。
设内联(+)(a:^t)(b:^t):^t=a+b
让内联(-)(a:^t)(b:^t):^t=a-b
让内联(*)(a:^t)(b:^t):^t=a*b
让内联(/)(a:^t)(b:^t):^t=a/b
让内联(~-)(a:^t):^t=-a
让内联半平方数=
设res=num/2G
res*res
设solve1=半正方形5I
设solve2=半正方形5.0
设solve3=半平方5uy
//定义更通用的数学函数。

我认为,一般来说,您需要一个
数值类/接口来实现这一点,而afaik在.net中还不存在(还?)。但也许一些特殊的F#东西可以帮你。看一看。你为什么问你是否应该用这个?使用
GenericXXX
的内联函数是在F#中实现这一点的最终方法。嗨,Daniel。我是F#的新手,我真的在尝试,这意味着我努力以功能性的方式来做,即使我脑海中尖叫的解决方案都是针对循环、副作用、gotos等等。现在,我非常不知道这是如何工作的引擎盖下,来自数字电子/微控制器的背景。我过去知道代码中每条指令的时间。我过去常常手工优化我的编译器输出。因此,这是一个诚实的问题,针对那些比我更了解这个主题的人。我可以做最愚蠢的事情,但我不知道。从这个背景来看,我认为这与C++模板是一样的。注意,
inline
无处不在。我之所以这么问,原因是:这家伙显然是复制了我的努力成果,并在两年前将其发布在这里。我的Google Fu很弱。这是一篇非常有趣的文章。没有真正关注整型->整型的东西,这让我想知道,这就是我所要求的在F#中真的那么不寻常吗?或者,这是一件小事,每个人都知道,而我是唯一一个在互联网上要求它的人?与此同时,在阅读了上述文章后,我想到了这个:让内联genericnn=let rec loop nIn nOut=if nInGenericZero then loop(nIn-GenericOne)(nOut+GenericOne)else nOut loop n GenericZero let inline halfSquare num=let res=num/(genericN 2)res*res问题
open System.Numerics

type FromInt = FromInt with
    static member ($) (FromInt, _:sbyte     ) = fun (x:int) -> sbyte      x
    static member ($) (FromInt, _:int16     ) = fun (x:int) -> int16      x
    static member ($) (FromInt, _:int32     ) = id
    static member ($) (FromInt, _:float     ) = fun (x:int) -> float      x
    static member ($) (FromInt, _:float32   ) = fun (x:int) -> float32    x
    static member ($) (FromInt, _:int64     ) = fun (x:int) -> int64      x
    static member ($) (FromInt, _:nativeint ) = fun (x:int) -> nativeint  x
    static member ($) (FromInt, _:byte      ) = fun (x:int) -> byte       x
    static member ($) (FromInt, _:uint16    ) = fun (x:int) -> uint16     x
    static member ($) (FromInt, _:char      ) = fun (x:int) -> char       x
    static member ($) (FromInt, _:uint32    ) = fun (x:int) -> uint32     x
    static member ($) (FromInt, _:uint64    ) = fun (x:int) -> uint64     x
    static member ($) (FromInt, _:unativeint) = fun (x:int) -> unativeint x
    static member ($) (FromInt, _:bigint    ) = fun (x:int) -> bigint     x
    static member ($) (FromInt, _:decimal   ) = fun (x:int) -> decimal    x
    static member ($) (FromInt, _:Complex   ) = fun (x:int) -> Complex(float x,0.0)  

let inline fromInt (a:int) : ^t = (FromInt  $  Unchecked.defaultof< ^t>) a

module NumericLiteralG =
    let inline FromZero() =LanguagePrimitives.GenericZero
    let inline FromOne() = LanguagePrimitives.GenericOne
    let inline FromInt32 (i:int)     = fromInt i


// This will reduce the number of types inferred, will reduce compile time too.
let inline (+) (a:^t) (b:^t) : ^t = a + b
let inline (-) (a:^t) (b:^t) : ^t = a - b
let inline (*) (a:^t) (b:^t) : ^t = a * b
let inline (/) (a:^t) (b:^t) : ^t = a / b
let inline (~-) (a:^t) : ^t = -a


let inline halfSquare num =
   let res = num / 2G
   res * res

let solve1 = halfSquare 5I 
let solve2 = halfSquare 5.0
let solve3 = halfSquare 5uy 

// Define more generic math functions.