在typeclass实例中提供函数类型签名会给出错误

时间:2019-08-14 20:08:51

标签: haskell type-signature

一旦我成功解决了Functor类型类的练习:

data ExactlyOne a = ExactlyOne a deriving (Eq, Show)

instance Functor ExactlyOne where
  (<$>) ::
    (a -> b)
    -> ExactlyOne a
    -> ExactlyOne b
  (<$>) f a = ExactlyOne $ f (runExactlyOne a)

解决另一个练习,我需要为自定义Odd类型定义Enum类型类函数。

data Odd = Odd Integer
  deriving (Eq, Show)

instance Enum Odd where
  -- succ :: Odd -> Odd <-- error
  succ (Odd x) = Odd $ x + 2

现在,当我尝试为更简单的功能指定类型签名时,ghci给出了一个错误:

  

实例声明中的非法类型签名:      succ ::奇数->奇数(使用InstanceSigs允许)

没有它就可以工作,但是我想知道为什么会产生此错误,以及如何为此功能正确指定类型签名?

1 个答案:

答案 0 :(得分:6)

实例中的签名对于类型类中的类型签名是多余的。如果您稍后稍稍更改类型类的签名(例如,通过添加额外的类型约束),则可能仅由于签名不再协调而可能导致错误。

这是在section on Instance Declarations in the Haskell '10 report中指定的:

  

声明不得包含任何类型签名或固定性声明,因为这些声明已在类声明中提供。与默认类方法(第4.3.1节)一样,方法声明必须采用变量或函数定义的形式。

Enum typeclass [src]已包含签名:

class  Enum a   where
    -- | the successor of a value.  For numeric types, 'succ' adds 1.
    succ                :: a -> a
    -- ...

但是,如果您想指定签名,则可以打开InstanceSigs language extension [ghc-doc],例如:

{-# LANGUAGE InstanceSigs #-}

data Odd = Odd Integer deriving (Eq, Show)

instance Enum Odd where
  succ :: Odd -> Odd
  succ (Odd x) = Odd $ x + 2