简体   繁体   中英

Haskell type classes and instances

Why does the code below require a constraint and the type parameter for an instance of Show but are they need required for making Quad an instance of Functor ?

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) 

Your definition of Show requires show be applied to each value wrapped by the Quad data constructor, which imposes the constraint. It would not be needed if you had a trivial instance like

instance Show (Quad a) where
    show (Quad a b c d) = "some Quad value"

because this definition doesn't care about the type of a et al.:

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

fmap , on the other hand, has type (a -> b) -> fa -> fb , because fmap itself places no constraint on the type used by Quad ; any such constraints are imposed by whatever function is passed to fmap as its first argument:

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

Sometimes, an instance for Functor will require a constraint. For example, consider the Compose type from Data.Functor.Compose :

data Compare f g = Compose { getCompose :: f (g a) }

Ignoring its name, all it requires is two type constructors with kind Type -> Type . But, if you want a Functor instance for Compose , then those type constructors must also have Functor instances, because we'll use fmap internally.

instance (Functor f, Functor g) => Functor (Compose f g) where
    -- x :: f (g a)
    fmap f (Compose x) = Compose (fmap (fmap f) x)

For example, fmap (+1) [1,2,3] == [2,3,4] , but fmap (+1) [[1,2,3], [4,5,6]] wouldn't typecheck, because (+1) can't take a list as an argument. Compose lets us "dig into" the nested functor.

-- Compose [[1,2,3],[4,5,6]] :: Num a => Compose [] [] a
> fmap (+1) (Compose [[1,2,3], [4,5,6]])
Compose [[2,3,4],[5,6,7]]

-- Compose [Just 3, Just 4, Nothing] :: Num a => Compose [] Maybe a
> fmap (+1) (Compose [Just 3, Just 4, Nothing])
Compose [Just 4,Just 5,Nothing]

-- Compose Nothing :: Compose Maybe g a
> fmap (+1) (Compose Nothing)
Nothing

-- Compose (Just [1,2,3]) :: Num a => Compose Maybe [] a
> fmap (+1) (Compose (Just [1,2,3]))
Compose (Just [2,3,4])

您呼叫show在“内部”四类型,以便它需要的实例Show ,但你是不是叫fmap在你的定义值“里面的”四fmapQuad ,所以没有理由要求它是Functor一个实例。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM