实例声明

时间:2017-09-20 07:32:01

标签: haskell

有点奇怪为什么在下面需要实例声明作为默认实现。

module Example where

class Eq a => EQ a where
    eq :: a -> a -> Bool
    eq = (==)

-- why is this instance declaration needed?
instance EQ Int where
    eq = (==)

f :: Int -> Int -> Bool
f = eq

如果我遗漏了实例声明,我会收到错误。我确信它已在Haskell报告中的某处解释过,但需要一段时间才能找到它。

1 个答案:

答案 0 :(得分:2)

我认为你是一个类的定义,可能更多的是Java / C#/ ...是class

如果你写:

class Eq a => EQ a where
    eq :: a -> a -> Bool
    eq = (==)

您只定义一个类型类:一种向函数类添加函数和写限制的方法。您已经写了每个Eq a都是EQ a ...您已经写过,为了实施EQ a,您必须实施Eq a同样(这里有点奇怪)。

此外,您提供了默认实现:eq = (==),但这只是实例的默认实现,您不指定实现。< / p>

写作:

instance EQ Int where
    eq = (==)

您现在已经定义IntEQ。您可以通过编写实例来使实例更有用:

instance Eq a => EQ a

现在您编写的文件不是a所拥有的所有类型Eq a,也是EQ的类型实例。但是,如果您这样写,那么您已经立即定义了EQ的整个Universum,因为在class定义中,您将a限制为EQ的实例,这意味着现在,在整个Haskell世界中,eq等于(==)

你可能想说:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}

class EQ a where
    eq :: a -> a -> Bool

instance Eq a => EQ a where
    eq = (==)

现在您定义了类型类EQ,对于a的每个类型Eq a,我们将eq设置为(==),但它允许您定义与其他类型相比EQ,例如data Foo不是Eq的实例。请注意,我们必须在此处启用两个扩展。这些是特定于编译器的,因此不属于标准Haskell。