尝试在Haskell中为我的Point3D类型定义Show时出现问题

时间:2011-01-14 10:53:34

标签: haskell functional-programming

我正在尝试为我的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'

我做错了什么?

3 个答案:

答案 0 :(得分:8)

type Point3D = (Integer, Integer, Integer)

此代码定义了一个名称:Point3D,它只是(Integer,Integer,Integer)的缩写。在每个上下文中,这两个类型表达式是等价的对于后者,Prelude已经定义了一个展示实例。

如果你真的需要3d点的不同字符串表示,你有以下选择:

  • 定义一个简单的函数formatPoint :: Point3D -> String
  • 将您的类型更改为与标准的3元组整数不同,例如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 ""