显示Haskell的实例

时间:2014-12-08 21:36:49

标签: haskell

我正在做我的作业,我在做一个Show的实例时遇到问题,我无法解决它,我尝试了很多东西。我将错误和我的代码复制到下面。

我的代码:

type Height = Float
type Width = Float
type Radius = Float
data Rectangle = Rectangle Height Width
data Circle = Circle Radius

class Shape a where
    area :: a -> Float
    perimeter :: a -> Float

instance Shape Rectangle where
    area (Rectangle h w) = h * w
    perimeter (Rectangle b a) = (2*b) + (2*a) 

instance Shape Circle where
    area (Circle r) = pi * r**2
    perimeter (Circle r) = 2*r*pi

type Volume = Float

volumePrism :: (Shape a) => a -> Height -> Volume
volumePrism base height = (area base) * height


surfacePrism ancho largo alto = (2*ancho*largo) + (2*largo*alto) + (2*ancho*alto)


instance Show a =>  Show (Shape a) where 
    show (Rectangle h w) = "Rectángulo de base " ++ w ++ "y altura " ++ h

错误说的是:

The first argument of 'Show' should have kind '*'

3 个答案:

答案 0 :(得分:9)

你想做什么是不可能的。 Shape是类型类,而不是数据类型,因此它没有可以模式匹配的构造函数。你可以做点什么

instance (Shape a) => Show a where
    show shape = "Area: " ++ show (area shape) ++ " Perimeter: " ++ show (perimeter shape)

但这似乎不是你想要的。相反,您应该分别为每种类型定义Show

instance Show Rectangle where
    show (Rectangle h w) = "Rectangle with base " ++ show w ++ " and height " ++ show h

instance Show Circle where
    show (Circle r) = "Circle with radius " ++ show r

关于“善意”的错误对于初学者来说可能是非常神秘的(有时候经验丰富的haskellers!),但在这种情况下它相当简单。但这确实涉及一个新概念。在Haskell中,您拥有具有类型的值,例如函数,常量,甚至是monadic动作。您还可以谈论“类型的类型”,即所谓的种类。有一对你应该知道并且习惯使用:*Constraint。您看到的大多数类型只涉及*和它们之间的箭头。所有“完全应用”的数据类型应该有类*,它基本上只是意味着它不接受任何类型参数,所以

> :kind Int
Int :: *
> :kind String
String :: *
> :kind IO ()
IO () :: *
> :kind Maybe Int
Maybe Int :: *
> :kind Either String Int
Either String Int :: *

但是,您也可以拥有更高级的类型:

> :kind IO    -- Note lack of ()
IO :: * -> *
> :kind Maybe
Maybe :: * -> *
> :kind Either
Either :: * -> * -> *

每个*只代表另一个完全应用的类型。最后一个细节很重要,这意味着你不能拥有Either IO Maybe,因为这将是一个荒谬的类型。这些也可以是更高阶:

> import Control.Monad.State
> :kind StateT
StateT :: * -> (* -> *) -> * -> *

它与函数类型的语法相同,只是没有类型变量。

您真正需要了解的另一个是Constraint。这个是专门针对类型类的:

> :kind Show
Show :: * -> Constraint
> :kind Num
Num :: * -> Constraint
> :kind MonadState
MonadState :: * -> (* -> *) -> Constraint

完全应用后,它们返回一个类型类,而不是数据类型。

如果您感到好奇,可以使用GHC扩展来处理更复杂的类型,甚至允许您指定类型或类型类的种类。你可以用它做一些有趣的技巧,但这些通常被认为是类型系统的更高级功能。

答案 1 :(得分:4)

Shape是一个类型类,你不能使类型类成为另一个类型类的实例。 (您可以将作为类型类实例的所有类型都设置为不同类型类的实例,但这似乎不是您在此处尝试执行的操作。)

相反,您似乎希望在Show上实施Rectangle。所以明确地说:

instance Show Rectangle where 
    show (Rectangle h w) = "Rectángulo de base " ++ w ++ "y altura " ++ h

答案 2 :(得分:1)

您的实例声明没有意义。翻译为英语,对于作为a的实例的每个Show,它将显示为" a的实例是Shape的实例{ {1}}"或者像那样难以理解的东西。

只需制作Show RectangleCircle个实例并离开Show,除非您要求Shape的每个实例都必须Shape的一个实例,您需要将其放入Show的声明中。