F#版本的haskell模式匹配

Jim*_*ffa 8 syntax f# haskell pattern-matching

我如何干净利落地在F#中使用它?

add 1 2 x = 3 + x
add 1 x y = 1 + x + y
add z x y = z + x + y
Run Code Online (Sandbox Code Playgroud)

yam*_*men 21

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

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
Run Code Online (Sandbox Code Playgroud)

用法如预期: add 1 2 3

如果你愿意使用元组作为参数(即放弃currying和部分应用),你甚至可以用简写来写它:

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
Run Code Online (Sandbox Code Playgroud)

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

  • @Jimmy:在`匹配z,x,y with`,`z,x,y`是一个单元组._add function_不接受单个值,但您只能匹配单个值. (4认同)

Don*_*art 8

回想一下Haskell 中函数一般形式作为带有模式的声明列表:

f pat1 ... = e1
f pat2 ... = e2
f pat3 ... = e3
Run Code Online (Sandbox Code Playgroud)

只是用于case分析的糖:

f x1 .. xn = case (x1, .. xn) of
                (pat1, ..., patn) -> e1
                (pat2, ..., patn) -> e2
                (pat3, ..., patn) -> e3
Run Code Online (Sandbox Code Playgroud)

所以可以使用模式匹配对其他语言进行相同的翻译,但没有声明级别的模式.


Jon*_*rop 5

这纯粹是语法上的.像Haskell,Standard ML和Mathematica这样的语言允许你写出不同的匹配案例,就像它们是不同的函数一样:

factorial 0 = 1
factorial 1 = 1
factorial n = n * factorial(n-1)
Run Code Online (Sandbox Code Playgroud)

而像OCaml和F#这样的语言要求你match在它的体内有一个单独的函数定义和使用或等价:

let factorial = function
  | 0 -> 1
  | 1 -> 1
  | n -> n * factorial(n-1)
Run Code Online (Sandbox Code Playgroud)

请注意,您不必使用此语法反复复制函数名称,并且可以更轻松地考虑匹配案例:

let factorial = function
  | 0 | 1 -> 1
  | n -> n * factorial(n-1)
Run Code Online (Sandbox Code Playgroud)

正如衙门写的那样,请用let f a b = match a, b with ...F#来讨价还价.

在经典的红黑树实现中,我发现标准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
Run Code Online (Sandbox Code Playgroud)

与等效的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)
Run Code Online (Sandbox Code Playgroud)