有点奇怪为什么在下面需要实例声明作为默认实现。
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报告中的某处解释过,但需要一段时间才能找到它。
答案 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 = (==)
您现在已经定义Int
是EQ
。您可以通过编写实例来使实例更有用:
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。