【问题标题】:F# version of haskell pattern matchF# 版本的 haskell 模式匹配
【发布时间】:2012-06-13 13:17:22
【问题描述】:

如何在 F# 中干净利落地执行这个 haskell?

add 1 2 x = 3 + x
add 1 x y = 1 + x + y
add z x y = z + x + y

【问题讨论】:

  • 我不知道haskell,这里的目标是什么?这看起来像是编译器会捕捉和解决的优化。我认为尝试在 F# 中编写具有模式匹配的等价物会更慢。你想达到什么目的?
  • gjvdkamp,它不是一种优化,它是一种使每个案例更易于阅读的句法设备。 f 1 = x; f 2 = y 被翻译成f a = case a of 1 -> x ; 2 -> y - haskell.org/onlinereport/decls.html#sect4.4.3.1

标签: haskell syntax f# pattern-matching


【解决方案1】:

不能重载函数本身,但可以直接使用模式匹配:

let add z x y =               // curried multiple parameters
    match z, x, y with        // convert to three-tuple to match on
    | 1, 2, x -> 3 + x
    | 1, x, y -> 1 + x + y
    | z, x, y -> z + x + y

按预期使用:add 1 2 3

如果你愿意使用元组作为参数(即放弃柯里化和偏应用),你甚至可以写得更简写:

let add =                     // expect three-tuple as first (and only) parameter
    function                  // use that one value directly to match on
    | 1, 2, x -> 3 + x
    | 1, x, y -> 1 + x + y
    | z, x, y -> z + x + y

现在的用法是:add (1, 2, 3)

【讨论】:

  • 谢谢!我一直在搜索 f# 模式匹配示例,但没有人匹配示例中的多个参数,给我的印象是您无法做到这一点。
  • @Jimmy :从技术上讲,这里匹配的是单个元组,所以你没有错......
  • @Jimmy :在match z, x, y with 中,z, x, y 是一个单元组。 add 函数 不接受单个值,但您只能匹配单个值。
  • @Jimmy : 不,add 函数是柯里化的,但它会采用柯里化参数 zxy 并使用它们来构造单个元组 @987654331 @,并匹配该元组。第二个选项直接采用单个元组,以便它可以使用function 速记。重点是,您只能通过首先将它们融合到单个对象中来匹配多个参数。
  • @JimmyHoffa “在 f# 中进行多个参数匹配时,currying 总是会丢失”。只是为了让你更困惑一点,这里所有的变量绑定都是模式,即使是以柯里化形式编写的。
【解决方案2】:

回想一下在 Haskell 中 general form of functions 作为带有模式的声明列表:

f pat1 ... = e1
f pat2 ... = e2
f pat3 ... = e3

只是case 分析的糖:

f x1 .. xn = case (x1, .. xn) of
                (pat1, ..., patn) -> e1
                (pat2, ..., patn) -> e2
                (pat3, ..., patn) -> e3

因此,可以对具有模式匹配但没有声明级模式的其他语言进行相同的翻译。

【讨论】:

  • 我意识到这只是一个案例,但是haskell中存在糖的原因是为了清洁,我希望f#中存在类似的东西,正如yamen指出的那样,f#中的匹配可以在同样的时尚
【解决方案3】:

这纯粹是句法。 Haskell、Standard ML 和 Mathematica 等语言允许您编写不同的匹配案例,就好像它们是不同的函数一样:

factorial 0 = 1
factorial 1 = 1
factorial n = n * factorial(n-1)

而像 OCaml 和 F# 这样的语言要求您有一个函数定义并在其主体中使用 match 或等效项:

let factorial = function
  | 0 -> 1
  | 1 -> 1
  | n -> n * factorial(n-1)

请注意,您不必使用此语法一遍又一遍地复制函数名称,并且可以更轻松地分解匹配案例:

let factorial = function
  | 0 | 1 -> 1
  | n -> n * factorial(n-1)

正如 yamen 所写,在 F# 中使用 let f a b = match a, b with ... 进行柯里化。

在经典的红黑树实现中,我发现标准 ML 和 Haskell 中函数名称和右侧的重复非常难看:

balance :: RB a -> a -> RB a -> RB a
balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d)
balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)
balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)
balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)
balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)
balance a x b = T B a x b

与等效的 OCaml 或 F# 相比:

let balance = function
  | B, z, (T(R, y, T(R, x, a, b), c) | T(R, x, a, T(R, y, b, c))), d
  | B, x, a, (T(R, z, T(R, y, b, c), d) | T(R, y, b, T(R, z, c, d))) ->
      T(R, y, T(B, x, a, b), T(B, z, c, d))
  | a, b, c, d -> T(a, b, c, d)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2021-05-22
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多