有这个:
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 h w) = 2*h+w*2
instance Shape Circle where
area (Circle r) = pi * r**2
perimeter (Circle r) = 2*pi*r
volumenPrism base height = (area base) * height
surfacePrism shape h = (area shape) * 2 + perimeter shape * h
为什么我不能写这个? a
是一种类型,为什么这不起作用?
instance (Shape a) => Eq a where
x==y = area x == area y
显然这样做:
instance Eq Circle where
x==y = area x == area y
首先是Circle,然后是Rectangle的工作......但似乎不是正确的方法。
我不知道这是什么?
泰
答案 0 :(得分:7)
基本问题是类型类实例解析机制没有回溯。因此,如果您编写instance Shape a => Eq a
,那么每当编译器想要找到Eq
实例时,编译器将尝试使用此实例,对于大多数类型,它将无法解决,因为它们不是Shape
。
如果您仍然想要这样做,可以添加
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
位于源文件的顶部。
您还可以通过将OverlappingInstances
添加到LANGUAGE编译指示集来解决上述问题,但您仍然会有Eq
的全局实例,这会导致其他地方出现严重混淆你的计划。
只要枚举你真正需要的实例,即使它看起来很丑,也要好得多。您可以使用辅助函数将样板文件保持在最小值,例如
x `areaEq` y = area x == area y
然后
instance Eq Circle where
(==) = areaEq
等