首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场

Show实例
EN

Stack Overflow用户
提问于 2014-12-08 21:36:49
回答 3查看 4.6K关注 0票数 2

我正在做作业,我在做一个演示的例子时遇到了问题,我无法解决它,我尝试了很多事情。我把错误和下面的代码复制给你。

我的代码:

代码语言:javascript
运行
复制
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

错误的意思是:

代码语言:javascript
运行
复制
The first argument of 'Show' should have kind '*'
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-12-08 21:40:18

Shape是一个类型集,您不能将一个类型集作为另一个类型集的实例。(您也可以将作为类型实例的所有类型设置为不同类型的实例,但这似乎不是您想要做的。)

相反,您似乎希望在Show上实现Rectangle。因此,明确地说:

代码语言:javascript
运行
复制
instance Show Rectangle where 
    show (Rectangle h w) = "Rectángulo de base " ++ w ++ "y altura " ++ h
票数 4
EN

Stack Overflow用户

发布于 2014-12-08 21:40:26

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

代码语言:javascript
运行
复制
instance (Shape a) => Show a where
    show shape = "Area: " ++ show (area shape) ++ " Perimeter: " ++ show (perimeter shape)

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

代码语言:javascript
运行
复制
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

关于“种类”的错误对于初学者来说可能是相当神秘的(有时也是经验丰富的哈奇勒人!),但在这种情况下,它是相当简单的。不过,这确实涉及到一个新的概念。在Haskell中,有一个类型的值,例如函数、常量,甚至是一元操作。你也可以谈论“类型的类型”,也就是所谓的类型。有几个您应该了解并乐于使用:*Constraint。您将看到的大多数类型只涉及*和它们之间的箭头。所有“完全应用”的数据类型都应该有类*,这基本上意味着它不接受任何类型的参数,所以

代码语言:javascript
运行
复制
> :kind Int
Int :: *
> :kind String
String :: *
> :kind IO ()
IO () :: *
> :kind Maybe Int
Maybe Int :: *
> :kind Either String Int
Either String Int :: *

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

代码语言:javascript
运行
复制
> :kind IO    -- Note lack of ()
IO :: * -> *
> :kind Maybe
Maybe :: * -> *
> :kind Either
Either :: * -> * -> *

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

代码语言:javascript
运行
复制
> import Control.Monad.State
> :kind StateT
StateT :: * -> (* -> *) -> * -> *

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

另一个你真正需要知道的是Constraint。这是专门为打字员准备的:

代码语言:javascript
运行
复制
> :kind Show
Show :: * -> Constraint
> :kind Num
Num :: * -> Constraint
> :kind MonadState
MonadState :: * -> (* -> *) -> Constraint

当完全应用时,它们返回类型类型,而不是数据类型。

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

票数 9
EN

Stack Overflow用户

发布于 2014-12-08 21:42:25

您的实例声明没有意义。翻译成英文,它会被读成“对于每一个aShow的实例,aShape的一个实例,是Show的一个实例”,或者类似的难以理解的东西。

只需创建RectangleCircle Show实例,并将Shape排除在外,除非您希望要求Shape的每个实例都必须是Show的实例,这是需要放入Shape声明中的内容。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27367419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档