假设我们有一个 typeclass class (A a, B a) => C a where
。使用newtype
将允许我们克隆数据类型,然后通过GeneralizedNewtypeDeriving
语言扩展自动派生实例(请参阅如何编写可派生类?和处理具有相同内部表示和最小样板的多种类型?)。
问题:是否有可能让 ghc 自动派生A
and C
,但使用我们自己指定的B
in deriving实现C
?
例如,以下代码(其中A
= Planet
、B
= Lives
、C
= Description
)无法按预期工作:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
module Main (main) where
data Cat = Cat String
newtype Dolphin = Dolphin Cat deriving (Planet)
------------------------------------------------
class Planet a where
planet :: a -> String
class Lives a where
lives :: a -> String
class (Planet a, Lives a) => Description a where
description :: a -> String
------------------------------------------------
instance Planet Cat where
planet _ = "lives on planet earth,"
instance Lives Cat where
lives _ = "lives on land"
instance Description Cat where
description a = (planet a) ++ (lives a)
------------------------------------------------
instance Lives Dolphin where
lives _ = "lives in the sea"
--want the following derivation to use the instance of
--"Lives" for "Dolphin" above
deriving instance Description Dolphin
------------------------------------------------
main = do
print $ description (Cat "test")
-- > "lives on planet earth,lives on land"
-- OK
print $ description (Dolphin (Cat "test"))
-- > "lives on planet earth,lives on land"
-- NOT OK. Want "lives on planet earth,lives in the sea"
我期待/想要的Dolphin
是Lives
在Description
.
显然,以下程序可以工作,但它需要一个显式实例化Description
for Dolphin
:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
module Main (main) where
data Cat = Cat String
newtype Dolphin = Dolphin Cat deriving (Planet)
------------------------------------------------
class Planet a where
planet :: a -> String
class Lives a where
lives :: a -> String
class (Planet a, Lives a) => Description a where
description :: a -> String
------------------------------------------------
instance Planet Cat where
planet _ = "lives on planet earth,"
instance Lives Cat where
lives _ = "lives on land"
instance Description Cat where
description a = (planet a) ++ (lives a)
------------------------------------------------
instance Lives Dolphin where
lives _ = "lives in the sea"
instance Description Dolphin where
description a = (planet a) ++ (lives a)
------------------------------------------------
main = do
print $ description (Cat "test")
-- > "lives on planet earth,lives on land"
--[OK]
print $ description (Dolphin (Cat "test"))
-- > "lives on planet earth,lives in the sea"
--[OK]
ps 令人费解的是,如果(在第一个程序中)我没有声明:
instance Lives Dolphin where
lives _ = "lives in the sea"
然后 ghc 抱怨:
Main.hs:36:1:
No instance for (Lives Dolphin)
arising from the superclasses of an instance declaration
In the instance declaration for ‘Description Dolphin’
如果 ghc没有在for的(自动)推导中使用它,instance Lives Dolphin where
它会抱怨缺少,这似乎很奇怪。Description
Dolphin