【问题标题】:Infix pattern matching中缀模式匹配
【发布时间】:2020-01-09 12:39:34
【问题描述】:

在 Haskell 中编程时有时会遇到一个问题,有时我想将模式与值匹配,但我只对值是否与模式匹配的真假信息感兴趣(例如,特定的数据类型构造函数)。例如:

data Color = 
    RGB Int Int Int 
  | Greyscale Int

toHex :: Color -> String
toHex color =
  if isGreyscale color then something
  else somethingElse

  where
  isGreyscale :: Color -> Bool
  isGreyscale (Greyscale _) = True
  isGreyscale _             = False

而我想在不创建不必要的辅助功​​能的情况下进行模式匹配,类似于:

toHex :: Color -> String
toHex color =
  if (color ~~ (Greyscale _)) then something
  else somethingElse

是否有特定的语法允许类似于上面的示例?或者在这种情况下会派上用场的成语?

【问题讨论】:

  • 除非我们已经有一个布尔值,否则if 通常是非常糟糕的,因为它迫使我们获取丰富的数据并剥离所有内容,直到我们有一个布尔值。 if condition 本质上是一个非常有限的case condition of True -> ... ; False -> ...,与一般的case 不同,它从不将值绑定到变量——这是模式匹配的关键部分。在您的情况下,要获得布尔值,您将丢弃Grayscale value 中的value,而case 会保留它。不要为boolean blindness受苦!
  • 您可能会感兴趣:A Crossroad at a Branch.
  • 一个丑陋但偶尔有用的成语:if null [ () | Greyscale _ <- color ] ...

标签: haskell functional-programming algebraic-data-types


【解决方案1】:

我不相信存在(或不可能存在)中缀运算符,因为模式不是值;这是语法。

您正在寻找case 表达式

toHex :: Color -> String
toHex color = case color of
               Greyscale _ -> something
               otherwise -> somethingElse

虽然你通常会这样写

toHex :: Color -> String
toHex (Greyscale _) = something
toHex _ = somethingElse

这本质上对上面的代码没有意义。

GHC 中还有 LambdaCase 扩展,它允许你编写以下内容,消除其他不必要的变量 color

{-# LANGUAGE LambdaCase #-}


toHex :: Color -> String
toHex = \case 
          Greyscale _ -> something
          otherwise -> somethingElse

【讨论】:

    【解决方案2】:

    您可以在函数定义中使用模式匹配来确定值:

    toHex :: Color -> String
    toHex (Greyscale _) = something
    toHex _ = somethingElse
    

    第一个模式匹配灰度值而不考虑整数值,第二个子句匹配其他所有值。如果somethingsomethingElse 是需要参数详细信息的函数,您可以轻松捕获它们:

    toHex :: Color -> String
    toHex (Greyscale g) = something g
    toHex (RGB r g b) = somethingElse r g b
    

    【讨论】:

      【解决方案3】:

      您可以使用multi-way if-expressions 和模式保护来获得几乎完全符合您需要的语法:

      {-# LANGUAGE MultiWayIf #-}
      
      toHex :: Color -> String
      toHex color =
        if | Greyscale _ <- color -> something
           | otherwise -> somethingElse
      

      【讨论】:

        猜你喜欢
        • 2015-07-29
        • 2022-01-11
        • 1970-01-01
        • 2020-05-19
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 2012-11-17
        • 1970-01-01
        相关资源
        最近更新 更多