class (A a, B a) => C a where
이라는 typeclass가 있다고 가정합니다. newtype
을 사용하면 데이터 유형을 복제 한 후 GeneralizedNewtypeDeriving
언어 확장을 통해 인스턴스를 자동으로 파생시킬 수 있습니다 (how to write a derivable class? 및 Handling multiple types with the same internal representation and minimal boilerplate? 참조).GeneralizedNewtypeDeriving을 통해 인스턴스를 파생 할 때 사용자 정의 인스턴스 사용
질문 : 자동 A
및 C
을 유도하기 위해 GHC를 얻을 수 있지만, C
을 도출 B
우리 자신의 지정된 구현을 사용할 수 있습니까? 다음 코드 예를 들어
(여기서 A
= Planet
= Lives
B
는 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"
내가 기다리고 있었다 무엇/
Lives
의
Dolphin
인스턴스에 대한 원한
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]
추신을
이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
이것이 일은 당신이 PID
에 ==
를 호출 할 때, 즉
instance Eq PID where
(PID x) == (PID y) = x == y
처럼 보이는 인스턴스를 작성, 그것은 일반에 그것을 펼쳤다 :
는'that'에 설명 메서드를 호출 한 후 고양이에 돌고래도를 풀기 및 것은 : 발생이되면, GHC 것 'instance Lives Cat where where '를 사용하지 마십시오.그렇다면 왜이 ghc 인스턴스는 첫 번째 프로그램에서 '돌고래가 살고있는 곳'에 불만이 있을까요? – artella
'질문 : 설명의 정의가 항상 같은 경우 왜 클래스가되어야합니까? 왜 이것을하는 정규 함수를 정의 할 수 없습니까? '이것은 내가 염두에 두었던 상황을 단순화 한 것입니다. 효율적으로 복잡한 유형 클래스 계층 구조를 상상하고 새로운 유형을 선언하고 모든 인스턴스를 재 선언 할 필요없이 해당 유형 클래스 계층 구조의 중간에있는 한 인스턴스의 동작 (주어진 유형의 경우)을 수정하려는 경우 하나의 인스턴스가 수정되었습니다. 이상적으로는 수정 된 인스턴스 만 선언하는 것이 좋습니다. – artella