通过GeneralizedNewtypeDeriving获取实例时使用自定义实例
假设我们有一个类型class (A a, B a) => C a where
。 使用newtype
将允许我们克隆一个数据类型,然后通过GeneralizedNewtypeDeriving
语言扩展自动派生实例(请参阅如何编写可派生类?以及使用相同的内部表示形式处理多个类型以及最少的样板?)。
问题 :是否有可能让ghc自动派生A
和C
,而是使用我们自己的指定实现B
来派生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"
我期望/想要的是在Description
的派生中调用Lives
的Dolphin
实例。
很明显,下面的程序是可行的,但它需要明确实例化Dolphin
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"
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会抱怨缺少instance Lives Dolphin where
如果它没有在Dolphin
的Description
(自动)派生中使用它。
考虑以下:
newtype ProcessID = PID Int deriving Eq
这样做是写一个看起来像的实例
instance Eq PID where
(PID x) == (PID y) = x == y
换句话说,当你在一个PID
上调用==
时,它将它解包到一个普通的Int
,然后执行==
。
我想象deriving instance Description Dolphin
完全一样; 将Dolphine
解Dolphine
成Cat
,然后调用description
方法。 这不是你想要的!
问题:如果description
的定义总是相同的,为什么它需要成为一个类? 为什么你不能只定义一个这样的常规函数?
(或者这是你想解决的一些更复杂问题的简化?)
链接地址: http://www.djcxy.com/p/7537.html上一篇: Using custom instance when deriving an instance via GeneralizedNewtypeDeriving