【问题标题】:Generic functions for generic types in F#F# 中泛型类型的泛型函数
【发布时间】:2019-01-29 18:02:48
【问题描述】:

我正在学习使用 F# 进行函数式编程,并且我想编写一个函数来提高数字的幂。我是这样写的:

let raiseToPower a power = 
    let folding x _ = x * a
    [1..power-1] |> List.fold folding a

let result = raiseToPower 2 5

我没有指定输入变量 a 的类型,所以我可以将此函数与浮点数或整数一起使用 - 但不能同时使用两者

let result = raiseToPower 2.3 5 // OK

// separate program let result = raiseToPower 2 5 // OK

// separate program let result1 = raiseToPower 2.3 5 // OK let result2 = raiseToPower 2 5 // fail

第一个问题是: 有没有办法让它通用?


我为 F# 已经具有内置实现的东西创建函数的原因是我想将类似的东西用于自定义类型 - 例如复数。

考虑以下几点:

type ComplexNumber = {re: double; im: double;}

let (@*) cn1 cn2 = 
    {re = cn1.re * cn2.re - cn1.im * cn2.im; im = cn1.re * cn2.im + cn1.im * cn2.re}

我有一个新类型 ComplexNumber 和一个新的运算符,用于将两个复数相乘。现在我可以编写一个类似的函数来提升ComplexNumber 的权力:

let raiseCnToPower a power = 
    let folding x _ = x @* a
    [1..power-1] |> List.fold folding a

所以第二个问题是: 有没有办法让初始函数与自定义类型和自定义运算符一起使用?


结论性问题: 我想知道你在函数式编程方面应该做什么。这是否被认为是一个问题,或者不同类型的不同功能几乎相同是可以的?有没有办法在函数式编程和 F# 方面改进解决方案?

【问题讨论】:

标签: functional-programming f#


【解决方案1】:

一个简单的方法是声明它inline:

let inline raiseToPower a power = 
    let folding x _ = x * a
    [1..power] |> List.fold folding (a / a) // <- handles power = 0

let result1 = raiseToPower 2 5
let result2 = raiseToPower 2. 5

【讨论】:

  • 为什么会有帮助?
  • let inline raiseToPower a power = List.replicate power a |&gt; List.fold ( *) LanguagePrimitives.GenericOne 也处理 power = 0,尽管不是 pown 比较。
  • 嘿,阿米尔!感谢您的回答!我有一个随之而来的问题:如果inline 在 F# 中的工作方式与它在例如 C++ 中的工作方式相同,并且编译器每次使用它时都会复制函数,这不是一个糟糕的解决方案吗?一般来说,函数式编程对inline 有什么看法?
  • @DmitryVolkov inline确实在调用点扩展,但它更强大。通过这样做,它传播使用的任何通用算术运算符的成员约束。它也具有传染性。
  • 据我所知,FP一般对inline的使用漠不关心。过度使用它们会使调试变得更加困难。对于通用算术运算,它们是一种简单而有效的解决方案。另一种方法是使用约束,但事实证明这些约束更难实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 2011-07-14
  • 1970-01-01
  • 2013-11-17
相关资源
最近更新 更多