t0m*_*ma5 4 haskell types ghci
有这个:
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
Run Code Online (Sandbox Code Playgroud)
为什么我不能写这个?a
是一种类型,为什么这不起作用?
instance (Shape a) => Eq a where
x==y = area x == area y
Run Code Online (Sandbox Code Playgroud)
显然这样做:
instance Eq Circle where
x==y = area x == area y
Run Code Online (Sandbox Code Playgroud)
首先是Circle,然后是Rectangle的工作..但它似乎不是正确的方法.
什么是我没有涉及到这一切?
泰
根本问题是类型类实例解析机制不会回溯.因此,如果您编写instance Shape a => Eq a
,那么每当编译器想要查找Eq
实例时,编译器将尝试使用此实例,对于大多数类型,它将无法解决,因为它们不是实例Shape
.
如果你真的想要这样做,你可以添加
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
Run Code Online (Sandbox Code Playgroud)
在源文件的顶部.
您还可以通过添加OverlappingInstances
LANGUAGE编译指示集来解决上述问题,但是您仍然会有一个全局实例,Eq
这将导致程序中其他地方出现严重混淆.
最好只列举你真正需要的实例,即使它看起来很难看.您可以使用辅助函数将样板保持在最小值,例如
x `areaEq` y = area x == area y
Run Code Online (Sandbox Code Playgroud)
然后
instance Eq Circle where
(==) = areaEq
Run Code Online (Sandbox Code Playgroud)
等等