I am trying to define Show for my Point3D
type:
type Point3D = (Integer, Integer, Integer)
instance Show Point3D where
show (x,y,z) = "<" ++ (show x) ++ "," ++ (show y) ++ "," ++ (show z) ++ ">"
yet I must 开发者_开发技巧be missing something in the sintax, as I am always getting an error:
Illegal instance declaration for `Show Point3D' (All instance types must be of the form (T t1 ... tn) where T is not a synonym. Use -XTypeSynonymInstances if you want to disable this.) In the instance declaration for `Show Point3D'
What am I doing wrong?
type Point3D = (Integer, Integer, Integer)
This code defines a name: Point3D
, which is just an abbreviation of (Integer,Integer,Integer)
. In every context these two type expressions are equivalent. And for the latter, there is already a show instance in the Prelude
defined.
If you really need a different string representation of 3d point you have the following alternatives:
- Define a simple function
formatPoint :: Point3D -> String
- Change your type to be different from a standard 3-tuple of integers, e.g.
newtype Point3D = P (Integer,Integer,Integer)
- Enable the language extensions mentioned in the error message.
I would defer enabling language extensions until you have mastered the core of Haskell, since they have the potential of being dangerous and or confusing.
The newtype solution changes only the syntax of values not their memory representation at runtime.
As alternative to the other proposals you can define Point3D as a record:
data Point3D = Point3D { x :: Int, y :: Int, z :: Int }
instance Show Point3D where
show (Point3D x y z) = concat ["<", show x, ",", show y, ",", show z, ">"]
Or you put the tripel inside a new type:
data Point3D = Point3D (Int, Int, Int)
instance Show Point3D where
show (Point3D (x,y,z)) = concat ["<",(show x),",",show y,",",show z,">"]
See http://learnyouahaskell.com/making-our-own-types-and-typeclasses for the pros and cons of these versions.
[Edit]
I learned that it's better to write the last version as
newtype Point3D = Point3D (Int, Int, Int)
instance Show Point3D where
show (Point3D (x,y,z)) = concat ["<",(show x),",",show y,",",show z,">"]
The newtype
keyword was made for exactly this kind of situation. The advantage over data
is that the compiler doesn't need to "wrap" the underlying type but can keep it as internal representation, which is both faster and "lazier".
Haskell separates the namespace of values and functions from the namespace of types, type classes, and modules by the case of the first letter of names. I.e. functions always have to start with a lowercase letter. While names of types have to start with an uppercase letter. Therefore the type class Show
requires a function show
.
Try it with:
type Point3D = (Integer, Integer, Integer) instance Show Point3D where show (x,y,z) = show ""
精彩评论