【问题标题】:Why `newtype` does not work with this pattern matching?为什么 `newtype` 不适用于这种模式匹配?
【发布时间】:2017-05-03 14:43:06
【问题描述】:

我通过将数据实现为Enum 来尝试以下代码。 而且,我有一个问题,只是将Enum 替换为newtype

这是我的测试代码。

newtype Fruit = Fruit Int deriving (Eq)

apple = Fruit 0
banana = Fruit 1
grape = Fruit 2
orange = Fruit 3

instance Show Fruit where
  show apple = "Apple"
  show banana = "Banana"
  show grape = "Grape"
  show orange = "Orange"
  show _ = "Fruit"

test =
  map show [apple, banana, grape, orange, (Fruit 5)]

我预计评估的test 将是["Apple","Banana","Grape","Orange","Fruit"],但它是["Apple","Apple","Apple","Apple","Apple"]

我认为 it 变量可能无法很好地与模式匹配一​​起使用,但我又通过case 尝试了一次,例如:

-- Fails: everything is "Apple"
instance Show Fruit where
  show g = case g of
    apple -> "Apple"
    banana -> "Banana"
    grape -> "Grape"
    orange -> "Orange"
    _ -> "Fruit"

为了确认我的临时代码,我再次尝试了下一个代码。

-- Fails: Works only for apple/banana. Variable does not work!
instance Show Fruit where
  show (Fruit 0) = "Apple"
  show (Fruit 1) = "Banana"
  show grape = "Grape"
  show orange = "Orange"
  show _ = "Fruit"

我可以得到["Apple","Banana","Grape","Grape","Grape"]

好吧,我可以用Enum 编写代码来实现,但我只是想了解为什么这些代码不能正常工作?

【问题讨论】:

  • 您应该使用data 而不是newtype 吗?
  • 旁注:show grapeshow orange 等同于 show _,因此模式重叠。编译器不会将橙色与上面的定义匹配,而是将其视为本地标识符。
  • 如果您只使用静态定义的水果,您应该真正使用 sum 类型来表示您的数据,而不是使用 Int 周围的包装器。例如:data Fruit = Apple | Banana | Grape | Orange deriving Eq

标签: haskell newtype


【解决方案1】:

这段代码

instance Show Fruit where
  show apple = "Apple"
  show banana = "Banana"
  show grape = "Grape"
  show orange = "Orange"
  show _ = "Fruit"

等价于

instance Show Fruit where
  show x = "Apple"
  show y = "Banana"
  show z = "Grape"
  show w = "Orange"
  show _ = "Fruit"

因为它声明了名为 apple, ... 的新变量,这些变量会影响全局定义的变量,而不会以任何方式与这些变量相关。

试试吧

instance Show Fruit where
  show x | x == apple = "Apple"
         | x == banana = "Banana"
         | x == grape = "Grape"
         | x == orange = "Orange"
         | otherwise = "Fruit"

要记住的经验法则是:在一个模式中,所有变量都是由模式定义的局部变量。

我建议使用 -Wall 打开警告,因为这会指出局部变量对全局变量的影响。

【讨论】:

  • 谢谢,我真的忘记了!但是,那为什么我使用的工具不能很好地工作呢?
  • @QuietJoon case 与多个方程没有区别。 case 也使用模式,它声明新的局部变量......同样的问题。
【解决方案2】:

您似乎正在尝试做的另一种方法是使用PatternSynonyms

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多