ZFunk
ZFunk

Reputation: 3

Applicative Instance of Pair Data Type in Haskell

I am trying to implement this pair data type as an applicative functor but I am told that 'a' is not in scope. I thought already stated what 'a' was in the instance declaration.

data Pair a b = Pair a b deriving (Show)

instance Functor (Pair a) where 
    fmap f (Pair a b) = Pair a (f b)

instance Applicative (Pair a) where
    
    pure x = Pair a x
    Pair a f <*> Pair a' x = Pair (a + a') (f x)

Upvotes: 0

Views: 359

Answers (2)

Iceland_jack
Iceland_jack

Reputation: 7014

You can also derive it via the new Generically1 applied to Sum a

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia        #-}

import GHC.Generics (Generic1, Generically1(..))
import Data.Monoid  (Sum(..))

data Pair a b = Pair a b
  deriving
  stock (Show, Generic1)

  deriving (Functor, Applicative)
  via Generically1 (Pair (Sum a))

Upvotes: 0

chepner
chepner

Reputation: 532313

a is a type variable, not something you can use in the definition of pure. pure needs some way of getting a value of type a to pair with x. There are a few ways you could do that:

  1. A function of type b -> a that you could apply to x.
  2. A function of type () -> a that you could apply to ().
  3. Some predefined value of type a.

The Applicative instance of (,) a takes the third approach, by requiring that a have a Monoid instance so that you can define pure in terms of mempty.

instance Monoid a => Applicative (Pair a) where
    pure x = Pair mempty x
    Pair a f <*> Pair a' x = Pair (a <> a') (f x)

In your definition, you assumed that (+) is defined for the a values, which means you are missing a Num constraint, but also that you could simply use 0 in your definition of pure.

instance Num a => Applicative (Pair a) where
    pure x = Pair 0 x
    Pair a f <*> Pair a' x = Pair (a + a') (f x)

Upvotes: 2

Related Questions