如何在没有派生的情况下实例化

Von*_*fry 3 haskell instance typeclass

抱歉我的英语不好.标题可能无法解释我的意思.

在Data.Tree中,Tree定义如下:

-- | Multi-way trees, also known as /rose trees/.
data Tree a = Node {
        rootLabel :: a,         -- ^ label value
        subForest :: Forest a   -- ^ zero or more child trees
    }
#ifdef __GLASGOW_HASKELL__
  deriving (Eq, Read, Show, Data)
#else
  deriving (Eq, Read, Show)
#endif
Run Code Online (Sandbox Code Playgroud)

它使用deriving到实例==,并/=Tree(日期).

我可以在没有推导的情况下做同样的事情吗?我尝试这样的事情:

data Test a = Test a
instance Eq Test where
    (Test a) == (Test b) = a == b
Run Code Online (Sandbox Code Playgroud)

但它引发了一个例外.我认为原因是关于a和b的类型.

什么我可以做我是否要定义我的数据的自定义操作==.

我知道我可以使用Functorfmap做到这一点.但我想使用==a == b地方a = Test 1b = Test "a".可能吗?

Wil*_*sem 9

可以定义instanceEqTreeTest,但也有一些问题,你的定义.

instance Eq Test where
    (Test a) == (Test b) = a == b
Run Code Online (Sandbox Code Playgroud)

第一个是Testin 仍然Eq Test参数化的.实际上,你写的这意味着有一个类型参数.所以你可以用:data Test a = ...

instance Eq (Test a) where
    (Test y) == (Test x) = x == y
Run Code Online (Sandbox Code Playgroud)

现在,您指定了Eq已定义的内容Test a.我也改名abxy.这是不必要的,因为"类型世界"和"变量世界"是分开的,但它使事情变得不那么混乱.

但仍有问题:你打电话x == y.但是没有担保人a本身就是一个例子Eq.因此,您需要使用类型约束:

instance Eq a => Eq (Test a) where
    (Test y) == (Test x) = x == y
Run Code Online (Sandbox Code Playgroud)

现在,您可以指定Test a为实例Eq ,如果 a是的实例Eq为好.

为了您的Tree数据结构中,instanceEq因此应该是这样的:

instance (Eq a, Eq (Forest a)) => Eq (Tree a) where
    (Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2
Run Code Online (Sandbox Code Playgroud)

(当然,我在这里定义如何两棵树都是平等的,有可能要定义在(语义)不同的方式平等了两棵树,所以你不应该本身复制粘贴此代码).

需要注意的是-像@luqui说-如果type Forest a = [Tree a],那么你可以省略Eq (Forest a)类型约束,自instance Eq a => Eq [a]成立.所以在这种情况下它是:

instance Eq a => Eq (Tree a) where
    (Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2
Run Code Online (Sandbox Code Playgroud)