Haskell类型类和实例

时间:2019-08-21 15:56:22

标签: haskell type-inference typeclass functor

为什么下面的代码为Show的实例要求一个约束和类型参数,但是为使QuadFunctor的实例需要它们吗?

data Quad a = Quad a a a a 
instance (Show a) => Show (Quad a) where
  show (Quad a b c d) = show a ++ " " ++ show b ++ "\n" ++ 
                        show c ++ " " ++ show d
instance Functor Quad where 
  fmap f (Quad a b c d) = Quad (f a) (f b) (f c) (f d) 

2 个答案:

答案 0 :(得分:3)

您对Show的定义要求将show应用于Quad数据构造函数包装的每个值,这会施加约束。如果您有一个琐碎的实例,例如

,则不需要
instance Show (Quad a) where
    show (Quad a b c d) = "some Quad value"

因为此定义不关心a等的类型:

> show (Quad 1 2 3 4)
"some Quad value"
> show (Quad (+1) (+2) (+3) (+4))
"some Quad value"

另一方面,

fmap的类型为(a -> b) -> f a -> f b,因为fmap本身对Quad使用的类型没有约束;任何这样的约束都是通过将函数作为第一个参数传递给fmap来施加的:

> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> :t fmap show
fmap show :: (Functor f, Show a) => f a -> f String

有时,Functor 的实例将需要一个约束。例如,考虑来自Compose的{​​{1}}类型:

Data.Functor.Compose

忽略它的名称,只需要两个类型为data Compare f g = Compose { getCompose :: f (g a) } 的类型构造函数即可。但是,如果您想要Type -> Type的{​​{1}}实例,则这些类型构造函数还必须具有Functor实例,因为我们将在内部使用Compose

Functor

例如fmap,但是instance (Functor f, Functor g) => Functor (Compose f g) where -- x :: f (g a) fmap f (Compose x) = Compose (fmap (fmap f) x) 不会进行类型检查,因为fmap (+1) [1,2,3] == [2,3,4]不能将列表作为参数。 fmap (+1) [[1,2,3], [4,5,6]]让我们“深入”嵌套函子。

(+1)

答案 1 :(得分:0)

您正在对类型“ inside” Quad中的show进行调用,因此它必须是Show的实例,但是您不会对值inside中的Quad中的值fmap进行调用您在fmap上对Quad的定义,因此没有理由要求它是Functor的实例。