Let's say I have:
data MyType
myToDouble :: MyType -> Double
Let's say I want MyType to b开发者_开发知识库e an instance of Num or Real or something that Double is already an instance of.
Is there a simple way to accomplish that without having to manually writing out all the methods in Num/Real for it?
So... is there some way of just saying:
instance Real MyType by way of myToDouble
Definitely not; Real
depends on Num
, and Num
has methods which return a
(or more accurately, are covariant in a
). How are you going to implement:
(+) :: MyType -> MyType -> MyType
given just MyType
and myToDouble
?
Now maybe you already have all the other instances and are just wondering about Real
. Well, the only method Real
has is of its own toRational
, so:
instance Real MyType where
toRational = toRational . myToDouble
As for your more general question: unfortunately not. If you have a class whose methods are all contravariant (only take as arguments) in the type variable, then you should be able to automatically define a typeclass on a projection like this. But Haskell has no mechanism to do so. (You could write one yourself using Template Haskell).
You can "forward" a newtype's instances to its underlying type using GeneralizedNewtypeDeriving
. Eg.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype MyType = MyType Double
deriving (Eq,Ord,Show,Num,Real)
But you can't use any old isomorphism. It's a shame.
精彩评论