typeclass があるとしますclass (A a, B a) => C a where
。を使用すると、データ型を複製し、言語拡張機能newtype
を介してインスタンスを自動的に派生させることができます(派生可能なクラスを作成する方法と、同じ内部表現と最小限の定型文で複数の型を処理する方法を参照してください)。GeneralizedNewtypeDeriving
質問: ghc にA
andを自動的に派生させることは可能ですが、派生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"
私が期待/望んでいたのは、 のDolphin
インスタンスがLives
の派生で呼び出されることでしDescription
た。
明らかに、次のプログラムは機能しますが、明示的にインスタンス化する必要がありDescription
ます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不可解なのは、(最初のプログラムで) if を宣言していないことです:
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’
forの(自動)派生でそれを使用していないinstance Lives Dolphin where
場合、 ghc が の不在について文句を言うのは奇妙に思えます。Description
Dolphin