我正在尝试为我的Point3D
类型定义Show:
type Point3D = (Integer, Integer, Integer)
instance Show Point3D where
show (x,y,z) = "<" ++ (show x) ++ "," ++ (show y) ++ "," ++ (show z) ++ ">"
然而我必须在sintax中遗漏一些东西,因为我总是收到错误:
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'
我做错了什么?
答案 0 :(得分:8)
type Point3D = (Integer, Integer, Integer)
此代码定义了一个名称:Point3D
,它只是(Integer,Integer,Integer)
的缩写。在每个上下文中,这两个类型表达式是等价的对于后者,Prelude
已经定义了一个展示实例。
如果你真的需要3d点的不同字符串表示,你有以下选择:
formatPoint :: Point3D -> String
newtype Point3D = P (Integer,Integer,Integer)
我会推迟启用语言扩展,直到你掌握了Haskell的核心,因为它们有可能带来危险或混乱。
newtype解决方案仅更改值的语法,而不是在运行时更改其内存表示。
答案 1 :(得分:6)
作为其他提案的替代方案,您可以将Point3D定义为记录:
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, ">"]
或者你把tripel放在一个新类型中:
data Point3D = Point3D (Int, Int, Int)
instance Show Point3D where
show (Point3D (x,y,z)) = concat ["<",(show x),",",show y,",",show z,">"]
有关这些版本的优缺点,请参阅http://learnyouahaskell.com/making-our-own-types-and-typeclasses。
<强> [编辑] 强>
我了解到将最后一个版本写为
会更好newtype Point3D = Point3D (Int, Int, Int)
instance Show Point3D where
show (Point3D (x,y,z)) = concat ["<",(show x),",",show y,",",show z,">"]
newtype
关键字就是针对这种情况而制作的。优于data
的优点是编译器不需要“包装”底层类型,但可以将其保留为内部表示,这样既快又“懒惰”。
答案 2 :(得分:0)
Haskell通过名字的第一个字母将值和函数的名称空间与类型,类型类和模块的名称空间分开。即函数总是必须以小写字母开头。虽然类型的名称必须以大写字母开头。因此,类型类Show
需要函数show
。
尝试使用:
type Point3D = (Integer, Integer, Integer) instance Show Point3D where show (x,y,z) = show ""