繁体   English   中英

不同类型之间的Haskell方程

[英]Haskell Eq between different types

我需要使用此数据结构data D = C Int Float并且需要将其与Int进行比较,例如a::D == 2

如何创建实例来定义这种Eq?

谢谢!

我将执行一个预测:

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

然后与之比较:

getInt myD == 5

您甚至可以将其包含在记录中:

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

如果你喜欢

你不能 ==具有签名a -> a -> Bool ,所以不能这样使用。

使用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

不依赖于convertible ,你可以只定义转换功能无论是从IntD (写a == fromInt 2 ),反之亦然。

不推荐使用的路线(对于这种特定情况,我认为它比第一种解决方案更糟糕)是定义自己的类型类,例如

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

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

instance Eq' D Int where ...

等等

可以这样做,但是我怀疑您会想要这样做。 正如Alexey提到的(==)的类型是Eq a=>a->a->Bool ,因此进行此工作的唯一方法是使2具有类型D 乍一看这似乎很荒谬,但实际上,可以使数字具有所需的任何类型,只要该类型是Num的实例即可

instance Num D where
    fromInteger x = C x 1.0

不过,仍有很多事情需要解决。

首先,您需要完全实现Num所有功能,包括(+)(*)abssignumfromInteger(negate | (-))

啊!

其次,您需要从Integer中填写额外的Float 我选择了上面的值1.0 ,但这是任意的。

第三,您还需要实际使D成为Eq的实例,以填写实际的(==)

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

请注意,这也是相当随意的,因为我需要忽略Float值以获取(==)来执行所需的操作。

最重要的是,这可以做您想要的事情,但是会以滥用Num类型和Eq类型为代价。... Num类型应该保留给您实际认为是数字,并且应该保留Eq类型以比较两个完整的对象,每个对象都包括在内。

暂无
暂无

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

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