Ros*_*hur 0 haskell operator-overloading
说我有这样的事情
class Circle c where
x :: c -> Float
y :: c -> Float
radius :: c -> Float
data Location = Location { locationX :: Float
, locationY :: Float
} deriving (Show, Eq)
data Blob = Location { blobX :: Float
, blobY :: Float
, blobRadius :: Float,
, blobRating :: Int
} deriving (Show, Eq)
instance Circle Location where
x = locationX
y = locationY
radius = pure 0
instance Circle Blob where
x = blobX
y = blobY
radius = blobRadius
Run Code Online (Sandbox Code Playgroud)
比方说,如果他们的x和y点相等,我希望Circle类型相等.如何将类型类的实例与(==)和(/ =)运算符进行比较.我知道我可以做这样的事情,但有可能超载运营商吗?
equal :: Circle a => Circle b => a -> b -> Bool
equal a b = (x a == x b && y a == y b)
Run Code Online (Sandbox Code Playgroud)
我想能够与之比较
(Location 5.0 5.0) == (Blob 5.0 5.0 ... ) 应该给我真实的
Zeroth,一些标准进口:
import Data.Function (on)
import Control.Arrow ((&&&))
Run Code Online (Sandbox Code Playgroud)
a==b应该只是,如果真的a和b是(用于与用户相关的所有目的)互换-这显然不是两个圆这只是碰巧共享相同的中心点的情况下!
其次,首先制作Circle类型类可能不是一个好主意.只有当你想要抽象不能仅用参数直接表达的东西时,类型类才有意义.但是如果你只是想将不同的"有效载荷"附加到空间中的点,那么更明智的方法可能是定义类似的东西
data Located a = Located {x,y :: ?, payload :: a}
Run Code Online (Sandbox Code Playgroud)
如果在某种情况下,您实际上希望允许不同的实例Circle共存并在运行时具有可比性,那么类型类完全是错误的选择.这将是一个OO类.Haskell没有任何内置的概念,但你可以使用
data Blob = Blob
{ x,y :: ?
, radius :: ?
, rating :: Maybe Int }
Run Code Online (Sandbox Code Playgroud)
而没有其他类型.
https://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/
第三,从理论上讲,你要求的实例可以定义为
instance (Circle a) => Eq a where
(==) = (==)`on`(x &&& y)
Run Code Online (Sandbox Code Playgroud)
但这将是一个非常可怕的想法.这将是一个包罗万象的实例:每当你比较任何东西时,编译器会检查"它的形式a是什么吗?"(字面意思是任何形式)"哦,很好,然后说实例告诉我如何比较它."以后会看看Circle要求.
在正确的解决方案是没有定义任何此类Eq的所有实例.你的类型已经Eq单独拥有实例,通常应该是正确使用的东西 - 根本不需要通过Circle类来表达它,只需给出需要做的任何函数来比较约束(Circle a, Eq a) => ....
当然,这些实例不仅可以比较位置,还可以比较整个数据,正如我所说,这是一件好事.如果你真的想只比较结构的一部分,那么,明确说明!不是==自己使用,而是提取相关部分并进行比较.对此有用的帮助可能是
location :: Circle a => a -> Location
location c = Location (x c) (y c)
Run Code Online (Sandbox Code Playgroud)
...然后,对于任何Circle类型,您可以简单地编写(==)`on`location而不是(==)忽略除位置之外的任何其他信息.或者(==)`on`(x &&& y)直接写出来,可以很容易地调整到其他情况.