为什么`newtype`不适用于这种模式匹配?

时间:2017-05-02 06:49:26

标签: haskell newtype

我通过将数据实现为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"]

我认为它变量可能不适用于模式匹配,但我再次尝试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,但我只是想了解为什么代码不能正常工作?

2 个答案:

答案 0 :(得分:5)

此代码

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打开警告,因为这会指出本地变量对全局变量的影响。

答案 1 :(得分:0)

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