"继承"类型(通过GeneralizedNewtypeDeriving)不使用派生实例

时间:2014-12-20 06:16:43

标签: haskell ghc typeclass

(与Using custom instance when deriving an instance via GeneralizedNewtypeDeriving相关)。假设我有:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main (main) where

data Cat = Cat String deriving (Show)
newtype Dolphin = Dolphin Cat deriving (Info,Show)

class Info a where
  info :: a -> (a,String)

instance Info Cat where
  info a = (a,show a)

main = do
  print $ info (Cat "mammal")
  --OK
  --OUTPUT 1 : (Cat "mammal","Cat \"mammal\"")

  print $ info (Dolphin $ Cat "mammal")
  --NOT OK
  --OUTPUT 2 : (Dolphin (Cat "mammal"),"Cat \"mammal\"")

  print $ show (Dolphin $ Cat "mammal")
  --OUTPUT 3 : "Dolphin (Cat \"mammal\")"

在输出2中,我们知道info正在对Dolphin类型的参数进行操作(请参阅元组的第一个元素),但它会打印出"Cat \"mammal\""的第二个元素元组的元素。但我们知道show类型的参数上执行的Dolphin应打印出"Dolphin (Cat \"mammal\")"(参见输出3)。那么为什么ghci(在输出2中)打印出"(Dolphin (Cat "mammal"),"Cat \"mammal\"")"时我认为它应该打印出来"(Dolphin (Cat "mammal"),"Dolphin (Cat \"mammal\")")"

1 个答案:

答案 0 :(得分:3)

具有任何代码的Info的唯一实例是Cat的实例,因此元组的第二个元素的唯一可能值是show (a :: Cat)的结果,它总是"Cat \"...\"" { {1}}。 Info的{​​{1}}实例来自Dolphin;它完全 GeneralizedNewtypeDeriving Info实例的内容。

Cat的{​​{1}}实例并非来自Show,它来自Dolphin的普通机制。它会像您期望的那样显示GeneralizedNewtypeDeriving。在第二个示例中,deriving (Show)实例使用Dolphin实例show (a :: Dolphin) Show来显示(Show a, Show b) => Show (a, b)类型的元组。

这里令人困惑的一点是print的{​​{1}}实例正在返回(Dolphin, String)类型的元组。 Info唯一要做的就是在Cat实例中出现的类型变量的每个地方用(Cat, String)替换GeneralizedNewtypeDeriving。这样可以Cat完全执行Dolphin所做的事情。