I have a question about type parameters that I think is best expressed by an example. This piece of code
newtype Triple a b c = T (a,b,c)
instance Functor (Triple a b) where
fmap f (T (x, y, z)) = T (x, y, (f z))
expresses triples as functors in their third variable.
How would I turn them into functors in their second variable?
How would I turn actual tuples (not my new type) into a functor?
The general question is: suppose I have a parametric type m a b c d e how do I express the parametric type m a b d e obtained by fixing one parameter? Or equivalently, how do I express the parametric type m a b d e c obtained by making an arbitrary parameter the last one?
Edit: it may not have become quite clear what I mean, so I'm trying to clarify: Triple has kind * -> * -> * -> *. So I can partially evaluate at two types to get something of kind * -> * which could be Functor or some other parametrized class. This evaluation is easy to do at the first two parameters but it is in principle possible at any two of the parameters, and I am asking how it can be done. This is essentially asking for a flip on the level of types.
As a concrete use case I can have three parametrized classes Functor, Foo, and Bar, and I want (Triple _ b c) to be a Functor, (Triple a _ c) to be a Foo, and (Triple a b _) to be a Bar (for all a, b, c). So then Triple a b c would be a Functor, a Foo and a Bar. You would think of writing these one-parameter types a -> Triple a b c, b -> Triple a b c and c -> Triple a b c but of course this literal notation expresses mapping types.
Edit2: Before posting a question on stackoverflow I always try to strip it to its abstract core, but this seems to obscure what I actually want. So a concrete variant of this question can now be found here.
This is what newtypes are for. You wrap an existing type up in a newtype, letting you do different stuff to it at the type level while leaving the value level unchanged. For example:
newtype SecondTriple a b c = SecondTriple (a, c, b)
instance Functor (SecondTriple a b) where
fmap f (SecondTriple (x, z, y)) = SecondTriple (x, f z, y)
If you like, you can wrap Triple instead of wrapping (,,), but of course you can't use Triple's Functor instance anyway so it's not much help.
In this specific case you might get what you need by using lenses.
The combination of over and all the functions in the tuple module (_1, _2, _3 etc.) gives you the ability to lift functions into more tuple positions than just the rightmost one.
EDIT Adding an example.
So say we have this tuple.
(1, "Foo", True)
And we want to (+ 1) to the value in its first position.
> import Control.Lens (over, _1)
> over _1 (+ 1) (1, "Foo", True)
(2,"Foo",True)
Or upper-case the string in its second position
> import Data.Char (toUpper)
> import Control.Lens (over, _2)
> over _2 (map toUpper) (1, "Foo", True)
(1,"FOO",True)
Or perhaps we want to flip the bool in its third position
> import Control.Lens (over, _3)
> over _3 not (1, "Foo", True)
(1,"Foo",False)
A functor has kind Type -> Type, so Triple :: Type -> Type -> Type -> Type itself is not a functor; only the nearly-saturated partial application Triple a b for 2 types a and b can be a functor.
Triple is, however, an example of a "trifunctor", which you can define yourself.
class Trifunctor p where
trimap :: (a -> x) -> (b -> y) -> (c -> z) -> p a b c -> p x y z
-- There are only so many synonyms for first, second, etc
map13 :: (a -> x) -> p a b c -> p x y z
map13 f = trimap f id id
map23 :: (b -> y) -> p a b c -> p x y z
map23 f = trimap id f id
map33 :: (c -> z) -> p a b c -> p x y z
map33 f = trimap id id f
instance Trifunctor Triple where
trimap f g h (Triple x y z) = Triple (f x) (g y) (h z)
The pattern generalizes; the product of n types is an n-functor.
Related
i am new to Haskell but i implemented this:
data Triple = T Double Double Double
instance Functor Triple where
fmap f (T a b c) = T (f a) (f b) (f c)
then i tried to make the Triple a Functor but
i get this message:
**error:
• Expected kind ‘* -> *’, but ‘Triple’ has kind ‘*’
• In the first argument of ‘Functor’, namely ‘Triple’
In the instance declaration for ‘Functor Triple**’
so my question is , do i really have to change the data Constructor to
data Triple a = a a a
???
this is my solution but is there a better one ?
yes, you need a * -> * Type for a Functor.
It has to be like this as the type of fmap is fmap :: (a -> b) -> f a -> f b - so as you can see f is applied to the type-parameter a in there.
So yep this would work:
data Triple a = T a a a
instance Functor Triple where
fmap f (T a b c) = T (f a) (f b) (f c)
* -> * means you need a type-constructor that is waiting for a Type and returns a Type.
For example:
Double has kind *
Triple(here) has kind * -> *
Triple Double has kind * again
it's like a curried function on the type-level ;)
you could write something like this for your Triple though:
data Triple = T Double Double Double
tripleMap :: (Double -> Double) -> Triple -> Triple
tripleMap (T a b c) = T (f a) (f b) (f c)
and maybe this is fine enough for you.
this is my solution but is there a better one ?
Well, depends on what you mean by “better”. Triple a makes a lot of sense, if it's not really specific for Double.
If you have good reasons to hard-code Double, then you can always just make a dedicated function for mapping over this data type, like tripleMap in Carsten's solution. There is also a widely used typeclass for this sort of operation though:
{-# LANGUAGE TypeFamilies #-}
import Data.MonoTraversable
type instance Element Triple = Double
instance MonoFunctor Triple where
omap f (T a b c) = T (f a) (f b) (f c)
Consider also whether it even makes sense to map arbitrary functions over your type. Maybe what you actually want is this?
import Data.AdditiveGroup
import Data.VectorSpace
data ℝ³ = ℝ³ Double Double Double
instance AdditiveGroup ℝ³ where
zeroV = ℝ³ 0 0 0
ℝ³ x y z ^+^ ℝ³ ξ υ ζ = ℝ³ (x+ξ) (y+υ) (z+ζ)
negateV (ℝ³ x y z) = ℝ³ (-x) (-y) (-z)
instance VectorSpace ℝ³ where
type Scalar ℝ³ = Double
μ *^ ℝ³ x y z = ℝ³ (μ*x) (μ*y) (μ*z)
The answer is yes, you need to define
data Triple a = T a a a
instance Functor Triple where
fmap f (T x y z) = T (f x) (f y) (f z)
I use x, y, z to stress that these are not types, but values.
Triple a is the type. Its values carry inside them three values of the same type, a, whichever that is in each specific case, like Double or whatever.
Since fmap :: (a -> b) -> f a -> f b, in the case of Triple it is fmap :: (a -> b) -> Triple a -> Triple b, and values of Triple b type carry inside them three values of the same type, b.
Thus we had to transform each of the three inside Triple Double, etc.
I need to write the Functor instances for the Flip datatype:
data K a b = K a
newtype Flip f a b = Flip (f b a) deriving (Eq, Show)
instance Functor (Flip K a) where
fmap=undefined
The solution I was given in class is:
instance Functor (Flip K a) where
fmap f (Flip (K b)) = Flip (K (f b))
I really don't understand what's going on here and I'm beginning to doubt my whole understanding of data types and functors. What I do understand is this (please correct me if any of this is wrong):
K is a data type that turns 2 parameters into a structure K a ( that only keeps the first parameter)
Flip is a datatype that turns 3 arguments into a structure with one
Because in fmap :: (a-> b) -> f a -> f b, f a has kind *, to write the Functor instance of Flip, we write it on the last type in Flip. Aka f and a are "constants" in a way, and we write the functor for the type b. I would write something like:
instance Functor (Flip f a) where
fmap f (Flip x y z) = fmap Flip x y (f z)
I know that that is completely wrong but I'm not sure why.
Also, why would we bring K into the Functor instance of Flip? Can someone explain thoroughly the process of coming up with this solution and why it is correct?
K is a data type that turns 2 parameters into a structure K a ( that only keeps the first parameter)
This isn't quite right. K a b is a data type formed using two parameters, but it's not really right to say that it "turns them into" anything. Instead, it's simply just stating to the world that there now exists a new type: K a b. "So what?" you might ask. Well, the second half of the data type defines how to make new values of this type. That part says, "You can make a new value of type K a b with this function I'll call K which has type a -> K a b." It's really important to recognize that there is a distinction between the type K and the constructor K.
So, it's not that K "only keeps the first parameter"—it's that the constructor K (which is a function) happens to not take any arguments of type b.
Flip is a datatype that turns 3 arguments into a structure with one
Just as above, this is not quite right. The Flip declaration states that there can be values of type Flip f a b, and the only way to make them is by using the constructor Flip that has type f b a -> Flip f a b.
In case you're wondering how I'm coming up with the type signatures for the constructors K and Flip, it's not actually mysterious, and you can double check by typing :t K or :t Flip into GHCi. These types are assigned based entirely on the right hand side of the data type declaration. Also, note that the type name and constructor don't have to be the same. For instance, consider this data type:
data Foo a = Bar Int a | Foo String | Baz a a
This declares a type Foo a with three constructors:
Bar :: Int -> a -> Foo a
Foo :: String -> Foo a
Baz :: a -> a -> Foo a
Basically, each of the types after the constructor name are the arguments, in order, to the constructor.
Because in fmap :: (a-> b) -> f a -> f b, f a has kind *, to write the Functor instance of Flip, we write it on the last type in Flip. Aka f and a are "constants" in a way, and we write the functor for the type b.
This is basically right! You could also say that f has kind * -> *. Since Flip has kind (* -> *) -> * -> * -> *, you need to provide it two type arguments (the first of kind * -> * and the second of kind *) to get it to the right kind. Those first two arguments become fixed ("constants" in a way) in the instance.
I would write something like: ... I know that that is completely wrong but I'm not sure why.
The reason your instance is completely wrong is that you've mixed up the type with the constructor. It doesn't make sense to put (Flip x y z) in the pattern position where you did because the constructor Flip only takes one argument—remember, it's type is Flip :: f b a -> Flip f a b! So you'd want to write something like:
instance Functor (Flip f a) where
fmap f (Flip fxa) = ...
Now, what do you fill in for the ...? You have a value fxa :: f x a, and you have a function f :: x -> y, and you need to produce a value of type f y a. Honestly, I don't know how to do that. After all, what is a value of typ f x a? We don't know what f is?!
Also, why would we bring K into the Functor instance of Flip? Can someone explain thoroughly the process of coming up with this solution and why it is correct?
We saw just above that we can't write the Functor instance for an arbitrary f, but what we can do is write it for a particular f. It turns out that K is just such a particular f that works. Let's try to make it work:
instance Functor (Flip K a) where
fmap f (Flip kxa) = ...
When f was arbitrary, we got stuck here, but now we know that kxa :: K x a. Remember that the only way to make a value of type K x a is using the constructor K. Therefore, this value kxa must have been made using that constructor, so we can break it apart as in: kxa ⩳ K x' where x' :: x. Let's go ahead and put that into our pattern:
fmap f (Flip (K x')) = ...
Now we can make progress! We need to produce a value of type Flip K a y. Hmm. The only way to produce a value of type Flip is using the Flip constructor, so let's start with that:
fmap f (Flip (K x')) = Flip ...
The Flip constructor at type Flip K a y takes a value of type K y a. The only way to produce one of those is with the K constructor, so let's add that:
fmap f (Flip (K x')) = Flip (K ...)
The K constructor at type K y a takes a value of type y, so we need to provide a value of type y here. We have a value x' :: x and a function f :: x -> y. Plugging the first into the second gives us the value we need:
fmap f (Flip (K x')) = Flip (K (f x'))
Just rename x' to b, and you have exactly the code your teacher provided.
DDub wrote in their answer:
You have a value fxa :: f x a, and you have a function f :: x -> y, and you need to produce a value of type f y a. Honestly, I don't know how to do that. After all, what is a value of type f x a? We don't know what f is?!
And I agree, but I woulld like to add a bit. Your teacher's idea as to how to deal with this is pretty cool (things like this K come in quite handy when you are trying to write down some counterexample, like here), and yet, I reckon we can make this code way broader. I use Data.Bifunctor.
So, what are Bifunctors? They are just what their name says: a * -> * -> * type (which we call bifunctors as well sometimes, yet they are not the same thing) which allows mapping over its both arguments (snippet from the source):
class Bifunctor p where
-- | Map over both arguments at the same time.
--
-- #'bimap' f g ≡ 'first' f '.' 'second' g#
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
bimap f g = first f . second g
{-# INLINE bimap #-}
-- | Map covariantly over the first argument.
--
-- #'first' f ≡ 'bimap' f 'id'#
first :: (a -> b) -> p a c -> p b c
first f = bimap f id
{-# INLINE first #-}
-- | Map covariantly over the second argument.
--
-- #'second' ≡ 'bimap' 'id'#
second :: (b -> c) -> p a b -> p a c
second = bimap id
{-# INLINE second #-}
So, here is how I would go about that:
instance Bifunctor f => Functor (Flip f a) where
fmap x2y (Flip fxa) = Flip (first x2y fxa)
Speaking of your teacher's code, it's a very nice idea, yet a more narrow one as K is a Bifunctor:
instance Bifunctor K where
bimap f _g (K a) = K (f a)
A lawful one:
bimap id id (K a) = K (id a) = id (K a)
As it says in the link above, having bimap only written down, that's the only law we need to worry about.
We just need to use sane and helpful naming, and suddenly it all becomes simple and clear (as opposed to torturous and contorted):
data K b a = MkK b -- the type (K b a) "is" just (b)
newtype Flip f a b = MkFlip (f b a) -- the type (Flip f a b) "is" (f b a)
deriving (Eq, Show)
instance Functor (Flip K a) where
-- fmap :: (b -> c) -> Flip K a b -> Flip K a c
fmap g (MkFlip (MkK b)) = MkFlip (MkK (g b))
-- MkK b :: K b a
-- MkFlip (_ :: K b a) :: Flip K a b
There's not even one question arising in our minds now looking at this, not one doubt we aren't able to immediately resolve.
Using same names for types and for data constructors while teaching, as well as using f both for "f"unction and "f"unctor, is pure abuse of the students.
Only when you've become fed up with all the Mks and don't feel they are helpful to you in any way, you can safely and easily throw them away, as experts usually do.
Suppose I have a type Pair:
data Pair a = Pair a a
What is the right way to write a monad instance for it? My idea is roughly this:
instance Semigroup a => Semigroup (Pair a) where
Pair a1 a2 <> Pair b1 b2 = Pair (a1 <> b1)(a2 <> b2)
instance Monad Pair where
return = pure
(Pair a b) >>= f = f a <> f b
Is it correct? If so then where to specify that b-type in the Pair b is a semigroup?
Actually, the only correct monad instance of Pair is as follows.
instance Monad Pair where
m >>= f = joinPair (f <$> m)
joinPair :: Pair (Pair a) -> Pair a
joinPair (Pair (Pair x _) (Pair _ y)) = Pair x y
The reason this is the correct monad instance is because Pair is a representable functor.
instance Representable Pair where
type Rep Pair = Bool
index (Pair x _) False = x
index (Pair _ y) True = y
tabulate f = Pair (f False) (f True)
Turns out, for every representable functor (>>=) is equivalent to the following bindRep function.
bindRep :: Representable f => f a -> (a -> f b) -> f b
bindRep m f = tabulate (\a -> index (f (index m a)) a)
If we specialize the bindRep function to Pair we get the following.
bindRep :: Pair a -> (a -> Pair b) -> Pair b
bindRep (Pair x y) f = tabulate (\a -> index (f (index (Pair x y) a)) a)
= Pair (index (f x) False) (index (f y) True)
-- |_________________| |________________|
-- | |
-- (1st elem of f x) (2nd elem of f y)
The following blog post by Adelbert Chang explains it better. Reasoning with representable functors.
Here's another way to prove uniqueness. Consider the left and right identity monad instance laws.
return a >>= k = k a -- left identity law
m >>= return = m -- right identity law
Now, for the Pair data type return x = Pair x x. Hence, we can specialize these laws.
Pair a a >>= k = k a -- left identity law
m >>= \x -> Pair x x = m -- right identity law
So, what should the definition of >>= be in order to satisfy these two laws?
Pair x y >>= f = Pair (oneOf [x1, x2, y1, y2]) (oneOf [x1, x2, y1, y2])
where Pair x1 y1 = f x
Pair x2 y2 = f y
The oneOf function returns one of the elements of the list non-deterministically.
Now, if our >>= function is to satisfy the left identity law then when x = y then x1 = x2 and y1 = y2 and the result must be Pair (oneOf [x1, x2]) (oneOf [y1, y2]).
Similarly, if our >>= function is to satisfy the right identity law then x1 = y1 = x and x2 = y2 = y and the result must be Pair (oneOf [x1, y1]) (oneOf [x2, y2]).
Hence, if you want to satisfy both laws then the only valid result is Pair x1 y2.
Functor and applicative instances are easy. The monad instance has taken a while to me.
data Pair a = Pair a a deriving (Eq, Show)
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
instance Applicative Pair where
pure a = Pair a a
(Pair f g) <*> (Pair a b) = Pair (f a) (g b)
instance Monad Pair where
return = pure
(Pair a b) >>= f = let Pair a' _ = f a
Pair _ b' = f b
in Pair a' b'
The way I've come to this solution is by applying the monad laws. Easily you can check with an example that identity law doesn't hold if you take Pair a' a'' or Pair b' b'' or Pair a' b' nor Pair a'' b''. So the only solutions must be in the diagonals. Defining
(m >>= f) = Pair (first . f . first $ m) (second . f . second $ m)
where first and second are the obvious ones, you can proof all of the laws.
It is possible to make Pair into Monad by having join that takes the diagonal.of the 2×2 square. return has no other choice but replicate its argument. This turns Pair into essentially a fixed length ZipList.
Of course this definition of join discards some data. This may or may not be important.
A Monad instance may not place any constraints on the type of data it contains (the a here). It must treat that data as fully opaque. I don't think your Pair type admits a Monad instance (or Applicative), because there is no way to turn a pair of pairs into a single pair without either losing some of the data, or using it in some way not permitted by the typeclass definition.
Why I am answering
I was curious to know what the practical usages of the Pair a monad are, especially considering that the only valid implementation of (>>=) actually throws away half of the data, so I asked this question.
It turns out that the answer I accepted is a very interesting answer to this question too (and was contained in Daniel Wagner's comment under the present question, but I hadn't noticed it), so I will elaborate it a bit here, because I've learned a lot from it.
The short answer: (a,a) and Bool -> a are the same thing
So the short answer is that the types Pair a, or more simply (a,a), and Bool -> a are isomorphic: feeding a (a,a) to fst/snd is equivalent to feeding a Bool -> a function with True/False (or False/True, it's just a choice). The two isomorphisms are actually shown in the (deleted) answer from Zhiltsoff Igor:
funToPair :: (Bool -> a) -> (a, a)
funToPair f = (f True, f False)
pairToFun :: (a, a) -> Bool -> a
pairToFun (x, y) True = x
pairToFun (x, y) False = y
As a consquence, whichever way Bool -> a is a monad, (a,a)/Pair a is a monad in the same way.
But (a,a)'s Monad throws information away... so does Bool -> a!
What bugged me at this point was that it's so apparent that the Monad instance for (a,a)/Pair a, thoroughly explained in Aadit M Shah's answer, throws away data, whereas the Monad instance for Bool -> a... doesn't...?
Fatally wrong! The Monad instance for r -> a (with generic r, not just Bool) throws away information all the time! How? Let's look at the well known implementation of >>=:
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
Now remember that a function of type x -> y is equivalent to a tuple of type (y,y,...,y) with as many entries as the number of possible values of type x (not y).
What about k? k is a binary function, let's say of type x -> y -> z, so it can be fed with the cartesian product of the values that inhabit the type x and those that inhabit the type of y. If x and y are inhabited by m and n values respectively, then k is equivalent to a tuple of type (z,z,...,z) with as many entries as m*n, and that is the information that comes with k.
Now the question is whether (>>=) makes use of all that information. No, it doesn't! (>>=) is feeding k with only n possible inputs: the second argument r is any value of type x, whereas the first argument is the single value corresponding to r via f.
If we think of mathematical functions, we are saying that, for fixed unary function f: A → B and binary function k: B×A → C, f >>= k is the unary function that does t ∈ A → k(f(t),t) ∈ C, i.e. it's a restriction of k to the curve parametrized by the equations x = f(t) and y = t.
Going back to Bool -> a, the signature of (>>=) specilizes to
(>>=) :: (Bool -> a) -> (a -> Bool -> b) -> Bool -> b
f >>= k = \r -> k (f r) r
which we can rewrite as follows, just to make the obvious more apparent:
(>>=) f k r
| r == True = k (f True) True
| r == False = k (f False) False
-- remember this
What's obvious in the above? If we feed f >>= k with True, we'll only use f True, thus throwing away the other half of the data, f False. Similarly, if we call (f >>= k) False, we throw away whatever f True is. This way of throwing away half of the information contained in k mirrors exactly what is throw away via the _ placeholders for (a,a) aka Pair a (adaptation from Ismor's answer):
instance Monad Pair where
return = pure
(Pair a b) >>= k = let Pair a' _ = k a
Pair _ b' = k b
in Pair a' b'
Indeed, if we define fst' (Pair a _) = a and snd' (Pair _ b) = b (these are mirroring fst and snd for (,)), then (>>=) can be written simply as follows
(>>=) :: Pair a -> (a -> Pair b) -> Pair b
p >>= k = (fst' (k (fst' p)),
snd' (k (snd' p)))
Which is in my opinion strikingly similar to the code I marked with -- remember this, with fst' mirrors True and snd' mirrors False.
By the way, for the following, let's take note of the type of (>>=) in the case we were allowed to write it for (a,a):
(>>=) :: (a,a) -> (a -> (b,b)) -> (b,b)
What about (a,b) when a and b are the same type?
This was the last doubt I had: since (a,b) is a Monad in b provided a is a Monoid, in the special case that the type b is equal to the type a (and b has to be a Monoid), do we get the same instance as above?
No, the question above is ill-posed, the flaw being in the part "in the special case that the type b is equal to the type a". This hypothesis is simply not possible because for a type constructor to be a Monad, it has to have one and only one free type parameter:
(a,b) is made a Monad in the free parameter b, meaning that b will be allowed to vary according to the second argument to (>>=), whereas the type a will stay the same through the (>>=) operator;
(a,a) is made a Monad in the free parameter a, meaning that a will be allowed to vary according to the second argument to (>>=), whereas... nothing, that's it, all explained in the previous part of the answer.
Lets say I've got the following:
data T a
f :: a -> (exists t. T t)
g :: T b -> c
h :: a -> c
h = g . f
As I know, the type signature for f is not valid Haskell. I can instead do this though:
{-# LANGUAGE GADTs #-}
data T a
data ExistsTA where
ExistsTA :: T a -> ExistsTA
f :: a -> ExistsTA
g :: T b -> c
h :: a -> c
h x = case (f x) of ExistsTA x' -> g x'
Which compiles fine. I was wondering, is there a library that generalises the creation of the ExistsTA data type (perhaps takes T as a parameter), or do I have to roll my own everytime I want to do this (which is not a big deal, just don't want to reinvent the wheel if I don't need too).
In particular, for my application, I would also like wrappers in this form:
data C where
C1 :: C
...
data D (a :: C) where
D1 a :: D
...
data T (d :: D) a
f :: T (D1 C1) a -> exists c. T (D1 c) a
I dunno whether this is in a library anywhere, but I like to use the following general-purpose existential:
data Ex f = forall a. Ex (f a)
With PolyKinds Ex can existentially wrap up the parameter of any type f :: k -> *. How general-purpose is this? We can manipulate f until it's the right shape, and we can build in whatever extra information we need, with a little library of type combinators. Working with general-purpose types like this is a powerful way to program, but often it's simpler just to roll your own.
Suppose we want to existentially quantify both halves of a two-parameter type p. One can use the following GADT to uncurry p, turning it from a two-parameter type k1 -> k2 -> * into a one-parameter type (k1, k2) -> *.
data Uncurry p ij where
Uncurry :: { getUncurry :: p i j } -> Uncurry p '(i, j)
Now Uncurry p can be existentially wrapped.
type ExP p = Ex (Uncurry p)
Suppose I want to pair up my existentially-wrapped type with some evidence such as a singleton, so that one can recover the existentially quantified index. I'll use the index-respecting product to pair up two functors f and g:
newtype (f :*: g) i = f i :*: g i
If, say, f is a GADT, pattern-matching on the f-half of the pair will tell you about g's index. Now, f :*: g has the right kind to be existentially wrapped.
type ExPair f g = Ex (f :*: g)
In practice you might write ExPair Sing f to pair up f with a singleton.
Suppose I need the aforementioned evidence in constraint form. I can replace Sing from above with the following type which reifies an instance dictionary for c a as a (visible) runtime value:
data Dict1 c a where
Dict1 :: c a => Dict1 c a
(or you could use the constraints package: newtype Dict1 c a = Dict1 { getDict1 :: Dict (c a) }.) Now I just need to set the left-hand part of my pair to be Dict1 c:
type ExDictPair c f = ExPair (Dict1 c) f
So you might write ExDictPair SingI f to package up an implicit singleton.
Suppose the thing I need to existentially quantify is at a higher kind, eg * -> *. (I might want to talk about "some instance of Monad containing an Int".) Ex is poly-kinded, but it only existentially quantifies the right-most parameter of its argument. So we need the * -> * part of the type to be the last argument of our datatype. I can write a type combinator for that too:
newtype RApp a f = RApp { getRApp :: f a }
type SomeMonadAppliedToInt = ExDictPair Monad (RApp Int)
import Control.Applicative
main = print $ fmap (*2) (1,2)
produces (1,4). I would expect it it to produce (2,4) but instead the function is applied only to the second element of the tuple.
Update I've basically figured this out almost straight away. I'll post my own answer in a minute..
Let me answer this with a question: Which output do you expect for:
main = print $ fmap (*2) ("funny",2)
You can have something as you want (using data Pair a = Pair a a or so), but as (,) may have different types in their first and second argument, you are out of luck.
Pairs are, essentially, defined like this:
data (,) a b = (,) a b
The Functor class looks like this:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Since the types of function arguments and results must have kind * (i.e. they represent values rather than type functions that can be applied further or more exotic things), we must have a :: *, b :: *, and, most importantly for our purposes, f :: * -> *. Since (,) has kind * -> * -> *, it must be applied to a type of kind * to obtain a type suitable to be a Functor. Thus
instance Functor ((,) x) where
-- fmap :: (a -> b) -> (x,a) -> (x,b)
So there's actually no way to write a Functor instance doing anything else.
One useful class that offers more ways to work with pairs is Bifunctor, from Data.Bifunctor.
class Bifunctor f where
bimap :: (a -> b) -> (c -> d) -> f a c -> f b d
bimap f g = first f . second g
first :: (a -> b) -> f a y -> f b y
first f = bimap f id
second :: (c -> d) -> f x c -> f x d
second g = bimap id g
This lets you write things like the following (from Data.Bifunctor.Join):
newtype Join p a =
Join { runJoin :: p a a }
instance Bifunctor p => Functor (Join p) where
fmap f = Join . bimap f f . runJoin
Join (,) is then essentially the same as Pair, where
data Pair a = Pair a a
Of course, you can also just use the Bifunctor instance to work with pairs directly.
The Functor instance is actually from the GHC.Base module which is imported by Control.Applicative.
Trying to write the instance I want, I can see that it won't work, given the definition of tuples; the instance requires just one type parameter, while the 2-tuple has two.
A valid Functor instance would at least have to be on tuples, (a,a) that have the same type for each element, but you cannot do anything sneaky, like define the instance on:
type T2 a = (a,a)
because instance types aren't permitted to be synonyms.
The above restricted 2-tuple synonym is logically the same as the type:
data T2 a = T2 a a
which can have a Functor instance:
instance Functor T2 where
fmap f (T2 x y) = T2 (f x) (f y)
As Gabriel remarked in the comments, this can be useful for branching structures or concurrency.