我正在做我的作业,我在做一个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 '*'
答案 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
Rectangle
个Circle
个实例并离开Show
,除非您要求Shape
的每个实例都必须Shape
的一个实例,您需要将其放入Show
的声明中。