【问题标题】:Adding two tuples of floats添加两个浮点数元组
【发布时间】:2021-10-10 02:23:36
【问题描述】:

我需要创建一个函数,将两个由浮点数组成的元组相加,并返回一个由两个浮点数组成的元组。

let add a b =
  fst a + fst b, snd a + snd b

给我这个回报:

val add : int * int -> int * int -> int * int

但如果我尝试:

let add (a:float) (b:float) =
  fst a + fst b, snd a + snd b

我明白了:

This expression was expected to have type
    ''a * 'd'    
but here has type
    'float'    

如何获得以下回报?

val add : float * float -> float * float -> float * float

【问题讨论】:

  • 使用这个let inline add a b = fst a + fst b, snd a + snd binline 是某种 F# 编译器魔法
  • 这不是魔法,它有明确的含义。

标签: function f# tuples


【解决方案1】:

如果您希望ab 的类型均为float * float,您可以直接指定:

let add (a : float * float) (b : float * float) = ...

或者您可以直接在参数声明中解构元组:

let add (a1:float, a2:float) (b1:float, b2:float) =
    (a1 + b1), (a2 + b2)

顺便说一句,您只需要指定其中一个元组的类型,另一个将根据它的元素添加到第一个元组的元素来推断:

let add (a1:float, a2:float) (b1, b2) =
    (a1 + b1), (a2 + b2)

或者,您可以标记函数inline

let inline add a b = ...

这意味着该函数不会被编译到 IL 中,而是会在每个使用站点进行扩展。反过来,这将使其能够与具有 + 运算符的任何类型一起使用。

编译为 IL 的非inline 函数不能这样做,因为 IL 不允许指定诸如“具有+ 运算符”之类的约束。但是编译器必须使用 some 类型,所以默认为int


另外,您可以防止编译器默认为int,方法是给它一些其他来源来推断类型。例如同一文件中的一个使用站点:

let add a b = ...

let x = add (1.0, 2.0) (3.0, 4.0)

最后一行会让编译器知道你期望参数是float

【讨论】:

    【解决方案2】:

    如果你知道元组总是包含浮点数,我认为最干净的方法是这样的:

    let add (ax : float, ay : float) (bx : float, by : float) =
        (ax + bx), (ay + by)
    

    【讨论】:

      猜你喜欢
      • 2014-08-23
      • 1970-01-01
      • 2023-03-07
      • 2015-10-03
      • 2017-05-30
      • 1970-01-01
      • 2021-04-05
      • 1970-01-01
      相关资源
      最近更新 更多