【问题标题】:Giving function type signature inside typeclass instance gives an error在 typeclass 实例中给出函数类型签名会出错
【发布时间】:2019-08-14 20:08:51
【问题描述】:

一旦我成功解决了 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 :: Odd -> Odd(使用 InstanceSigs 允许这样做)

没有它也可以,但是我想知道为什么会产生这个错误以及如何为这个函数正确指定类型签名?

【问题讨论】:

    标签: haskell type-signature


    【解决方案1】:

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

    这是在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

    【讨论】:

    • “这对于类型类本身的签名来说是多余的。” - 您的意思是指定类型类的实例吗?
    • @user4035:实例中的签名对于类型类中的类型签名是多余的。由于通过写instance Enum Odd,我们知道Enum a中的aa ~ Odd,因此succ :: Odd -&gt; Odd的签名是类级别的类型签名。
    猜你喜欢
    • 2019-04-27
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多