How do I create a functor instance for a type with two arguments, where both arguments have to be the same type?

The Unfun Cat

I have almost been able to create a valid functor instance for the type Pair. Problem is, Pair takes two arguments both of the same type, so when I write

fmap f (Pair a a') = Pair a (f a')

I cannot guarantee that the result is a valid Pair, since (f a') might be any type.

What is the Haskell way of ensuring this constraint?

import Test.QuickCheck
import Test.QuickCheck.Function

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

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

-- stuff below just related to quickchecking that functor instance is valid
main = quickCheck (functorCompose' :: PFC)

type P2P = Fun Int Int

type PFC = (Pair Int) -> P2P -> P2P -> Bool

instance (Arbitrary a) => Arbitrary (Pair a) where
  arbitrary = do
    a <- arbitrary
    b <- arbitrary
    return (Pair a b)

functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool
functorIdentity f = fmap id f == f

functorCompose :: (Eq (f c), Functor f) => (a -> b) -> (b -> c) -> f a -> Bool
functorCompose f g x = (fmap g (fmap f x)) == (fmap (g . f) x)

functorCompose' :: (Eq (f c), Functor f) => f a -> Fun a b -> Fun b c -> Bool
functorCompose' x (Fun _ f) (Fun _ g) = (fmap (g . f) x) == (fmap g . fmap f $ x)

Here is the error message I get, btw:

chap16/functor_pair.hs:22:29: Couldn't match expected type ‘b’ with actual type ‘a’ …
      ‘a’ is a rigid type variable bound by
          the type signature for fmap :: (a -> b) -> Pair a -> Pair b
          at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3
      ‘b’ is a rigid type variable bound by
          the type signature for fmap :: (a -> b) -> Pair a -> Pair b
          at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3
    Relevant bindings include
      a' :: a
        (bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:18)
      a :: a
        (bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:16)
      f :: a -> b
        (bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:8)
      fmap :: (a -> b) -> Pair a -> Pair b
        (bound at /Users/ebs/code/haskell/book/chap16/functor_pair.hs:22:3)
    In the first argument of ‘Pair’, namely ‘a’
    In the expression: Pair a (f a')
Compilation failed.

(This is an exercise from http://haskellbook.com/)

chi

Assume f :: t1 -> t2. We want fmap f :: Pair t1 -> Pair t2. Your attempt was:

fmap f (Pair a a') = Pair a (f a')
                       -- ^

which is ill-typed because a is of type t1 instead of type t2.

If only we had something that can transform t1 values into t2 values, we could simply use it on a and everything would type check. Do we have such a thing? ;-)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to write a monad instance for a pair where both arguments have the same type?

How can I specify type constraint to have same arguments in two predicates?

How can I instance `Functor` for a type with two parameters?

How do I use Typecript to create a generic API SDK where the return type is determined by a string literal passed in as an arguments?

How to make compiler check that 2 method arguments have the same type?

How can I ensure that arguments have same type without listing the types explicitly?

How to do type check in a way that two arguments have different values in TypeScritp?

How do I create an instance of a generic type?

Variadic templates - how can I create type, that stores passed arguments

Create variable of arguments type

how do I get the type of a methods arguments in typescript?

In TypeScript, how do i type a function's arguments but not the return value?

How do I specify type parameters as being function arguments in Rust?

TypeChecker API: How do I find inferred type arguments to a function?

ANTLR How to differentiate input arguments of the same type

How can i have two not arguments in an if statement

How can I force two instance variables to be of the same generic type?

Ensure arguments to generic method have same type in trait method

Functor Instance for Type Constructor with Two Parameters in Scala

How do I create a list with multiple types that have the same superclass, without losing the type

How do I fix one to many relationship where one side has two entities of the same type

How can I store the arguments of a variadic type?

How can I use type arguments in an ltac?

How can I tell rust two traits have the same type?

Can I create a function which takes any number of arguments of the same type?

Why do I have to explicitly specify my type arguments for Func parameters?

Decltype with two arguments modifies type

ngrx createFeatureSelector with two type arguments

How do I make Excel user-defined function (UDF) accept arguments of String type and range type?