简体   繁体   English

不同类型之间的Haskell方程

[英]Haskell Eq between different types

I need to use this data structure data D = C Int Float and I need to compare it with an Int, for example a::D == 2 . 我需要使用此数据结构data D = C Int Float并且需要将其与Int进行比较,例如a::D == 2

How can I create an instance to define this kind of Eq ? 如何创建实例来定义这种Eq?

Thank you! 谢谢!

I would implement a projection: 我将执行一个预测:

getInt :: D -> Int
getInt (C i _) = i

and then compare with it: 然后与之比较:

getInt myD == 5

you can even include this into a record: 您甚至可以将其包含在记录中:

data D = C { getInt :: Int, getFloat :: Float }

if you like 如果你喜欢

You can't; 你不能 == has signature a -> a -> Bool , so it can't be used like this. ==具有签名a -> a -> Bool ,所以不能这样使用。

Using the convertible package you can define 使用convertible包,您可以定义

(~==) :: (Convertible a b, Eq b) => a -> b -> Bool
x ~== y = case safeConvert x of
            Right x' -> x' == y
            Left _ -> False

(==~) :: (Convertible b a, Eq a) => a -> b -> Bool
(==~) = flip (~==)

instance Convertible Int D where ... 
-- or D Int depending on what you have in mind

Without depending on convertible , you could just define a conversion function either from Int to D (and write a == fromInt 2 ) or vice versa. 不依赖于convertible ,你可以只定义转换功能无论是从IntD (写a == fromInt 2 ),反之亦然。

A less recommended route (for this specific case I think it's simply worse than the first solution) would be to define your own type class, eg 不推荐使用的路线(对于这种特定情况,我认为它比第一种解决方案更糟糕)是定义自己的类型类,例如

class Eq' a b where
  (=~=) :: a -> b -> Bool

instance Eq a => Eq' a a where
  x =~= y = x == y

instance Eq' D Int where ...

etc. 等等

This can be done, but I doubt you will want to do this. 可以这样做,但是我怀疑您会想要这样做。 As Alexey mentioned the type of (==) is Eq a=>a->a->Bool , so the only way to make this work would be to make 2 have type D . 正如Alexey提到的(==)的类型是Eq a=>a->a->Bool ,因此进行此工作的唯一方法是使2具有类型D This may seem absurd at first, but in fact numbers can be made to have any type you want, as long as that type is an instance of Num 乍一看这似乎很荒谬,但实际上,可以使数字具有所需的任何类型,只要该类型是Num的实例即可

instance Num D where
    fromInteger x = C x 1.0

There are still many things to work out, though.... 不过,仍有很多事情需要解决。

First, you need to fully implement all the functions in Num , including (+) , (*) , abs , signum , fromInteger , and (negate | (-)) . 首先,您需要完全实现Num所有功能,包括(+)(*)abssignumfromInteger(negate | (-))

Ugh! 啊!

Second, you have that extra Float to fill in in fromInteger. 其次,您需要从Integer中填写额外的Float I chose the value 1.0 above, but that was arbitrary. 我选择了上面的值1.0 ,但这是任意的。

Third, you need to actually make D an instance of Eq also, to fill in the actual (==) . 第三,您还需要实际使D成为Eq的实例,以填写实际的(==)

instance Eq D where
    (C x _) == (C y _) = x == y

Note that this is also pretty arbitrary, as I needed to ignore the Float values to get (==) to do what you want it to. 请注意,这也是相当随意的,因为我需要忽略Float值以获取(==)来执行所需的操作。

Bottom line is, this would do what you want it to do, but at the cost of abusing the Num type, and the Eq type pretty badly.... The Num type should be reserved for things that you actually would think of as a number, and the Eq type should be reserved for a comparison of two full objects, each part included. 最重要的是,这可以做您想要的事情,但是会以滥用Num类型和Eq类型为代价。... Num类型应该保留给您实际认为是数字,并且应该保留Eq类型以比较两个完整的对象,每个对象都包括在内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM