【问题标题】:Fsharp: Passing N Parameters for a functionF Sharp:为函数传递 IN 参数
【发布时间】:2017-11-16 17:00:24
【问题描述】:

我正在尝试创建一个接受可变数量参数的函数,但我似乎无法为 F# 找到任何可行的解决方案。

let expression = (fun a b -> a || b)
let expressionTriple = (fun a b c -> (a || b) && c)

// This doesn't work because expression can either be a function that takes fixed arguments
let truthTable numPredicates expression =
    if numPredicates = 2 then
        expression true true
    else
        expression true true false


truthTable 2 expression
truthTable 3 expressionTriple

如何将可变数量的参数传递给表达式函数?

【问题讨论】:

  • 你想让truthTable 3 expression做什么?
  • truthTable 3 表示我传入的谓词数量
  • 是的,但是expression 只接受 2 个参数,所以expression true true false 通常是编译错误。

标签: f#


【解决方案1】:

在 F# 中,具有不同签名(包括不同数量的参数)的函数被视为不同的类型。并且任何时候你想让一个函数接受一个可以是两种不同类型(甚至是十几种不同类型)的参数,你需要使用discriminated unions。以下是您如何编写代码以编译并执行您正在尝试执行的操作:

type Expression<'a> =
    | Double of ('a -> 'a -> 'a)
    | Triple of ('a -> 'a -> 'a -> 'a)

let expression = fun a b -> a || b
let expressionTriple = fun a b c -> (a || b) && c

// This works because expression is a discriminated union
let truthTable expression =
    match expression with
    | Double f -> f true true
    | Triple f -> f true true false

truthTable (Double expression)
truthTable (Triple expressionTriple)

如果您想添加四参数版本,只需将 Quad of ('a -&gt; 'a -&gt; 'a -&gt; 'a -&gt; 'a) 案例添加到该可区分联合,等等。

如果您对此有任何疑问,例如为什么我使用泛型类型 'a 而不是 bool 来写这篇文章,请随时提出后续问题。

【讨论】:

  • 另一个选项是重载,但我不会使用重载来建模任意真值表。就是感觉不对。
  • 有没有办法将此扩展到任意 N 个参数?我目前的解决方法是使用 ParamArray github.com/rudresh4/discite/blob/…
  • 我从您的 Github 存储库中看到您正在解决 99 个问题集,这是第 48 个问题。到目前为止,我看到的唯一解决方案是将您的 expression 设为接受列表的函数。例如,fssnip.net/ar/title/… 的问题陈述希望您定义一个函数 tablen,它可以像 tablen 3 (fun [a;b;c] -&gt; a &amp;&amp; (b || c) = a &amp;&amp; b || a &amp;&amp; c) 一样调用。您的ParamArray 解决方案与此相差不远。
  • 但一般来说,不,你不能在 F# 中拥有带有 N 个任意参数的函数签名。正如您已经发现的,您可以使用作为单个参数传递的数组或列表。这个限制的原因是因为它会导致curryingpartial function application 出现问题:如果你的函数允许多个参数,编译器怎么知道你什么时候希望它被部分应用?所以为了允许柯里化,禁止使用多个参数。
【解决方案2】:
let expression = (fun [a; b] -> a || b)
let expressionTriple = (fun [a; b; c] -> (a || b) && c)

let truthTable numPredicates expression =
   if numPredicates = 2 then
      expression [true; true]
   else
      expression [true; true; false]


truthTable 2 expression 
truthTable 3 expressionTriple 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-02
    • 2013-11-04
    • 2010-09-07
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    相关资源
    最近更新 更多