In Haskell, what does ((->) t) mean in the type signature of instances? For example Functor, Applicative and Monad all have an instance along the lines of:
Functor ((->) r)
I can't find any explanation of what this type signature means and it's highly search engine-resistant.
-> is an infix type constructor. You can compare it with : - an infix value constructor for list type. To use : alone we put parentheses around it so it becomes a prefix function application:
(:) a b is the same as a : b
Similarly, (->) a b is the same as a -> b, type of a function from a to b.
(->) a is a partial application of type constructor, and itself a type constructor of kind * -> *.
You can think of it as "a constructor of types of functions from a". E.g. (->) Int is a constructor of types of functions from Int. You can construct full function type by passing another type to it: (->) Int String is the type of functions from Int to String.
instance Functor (->) a is a functor with fmap operation transforming an a -> b function into an a -> c function. You can compare it with a similar instance Functor (Either a) which maps Either a b to Either a c by applying the fmap argument to Right values.
We could use lambda functions and infix functions:
(->) a = \b -> (->) a b --pseudo-Haskell
(->) a = \b -> a -> b --pseudo-Haskell
so, read instance as:
class Functor f where
fmap :: (a->b) -> f a -> f b
instance Functor ((->)r) where
fmap :: (a->b) -> f a -> f b
= (a->b) -> (->)r a -> (->)r b --pseudo-Haskell
= (a->b) -> (r -> a) -> (r -> b) --pseudo-Haskell
You could see it as the set of types r -> a where r is fixed.
A functor is a type function m, which means that for any type a you have a type m a. Examples are Maybe, [] and (->) r. The latter should perhaps better be written (r ->), but I don't know if that's allowed.
Related
Suppose i have a datatype MayFail defined as following
data MayFail e a = Error e | Result a
deriving (Show)
So it's either a result or an error. I now want to write a Functor for it but this is where it gets confusing.
MayFail has two types, either e or a. So why do I have to write the functor as follows
instance Functor (MayFail e) where
fmap _ (Error e) = Error e
fmap f (Result x) = Result (f x)
and not instance Functor (MayFail e a) where?
What is the syntactic rule behind this?
Your question is a bit unclear, but I assume you're asking why you have to use e in instance Functor (MayFail e) instead of just writing instance Functor MayFail.
This is because Functor takes a type parameter of kind Type -> Type, and MayFail on its own would have kind Type -> Type -> Type. (Using MayFail e a would also be wrong, as its kind is just Type.)
MayFail :: Type -> Type -> Type is not a functor, but a bifunctor:
-- somewhat simplified definition
class Bifunctor p where
-- p :: Type -> Type -> Type
bimap :: (a -> c) -> (c -> d) -> p a b -> p c d
instance Bifunctor MayFail where
bimap f _ (Error e) = Error (f e)
bimap _ g (Result x) = Result (g x)
But, for any fixed error type e, the result of the partial application MayFail e :: Type -> Type is a functor:
instance Functor (MayFail e) where
fmap _ (Error e) = Error e
fmap f (Result x) = Result (f x)
-- Or, using the Bifunctor instance,
-- fmap = bimap id
In some sense, a bifunctor is a mapping of types to functors.
The Functor class is defined as
class Functor f where
fmap :: (a -> b) -> f a -> f b
That is, the type constructor f must accept a single type argument (otherwise f a and f b in the type signature of fmap would be invalid).
Formally this means f must have kind Type -> Type (also known as * -> * in older versions of GHC).
This is different from e.g. Eq or Show, which look like this (simplified):
class Eq a where
(==) :: a -> a -> Bool
class Show a where
show :: a -> String
Here the parameter a is used as a type itself.
Your type, data MayFail e a, has two parameters. If we were to plug just MayFail into the Functor definition, as in
instance Functor MayFail where ...
this would implicitly declare fmap as
fmap :: (a -> b) -> MayFail a -> MayFail b
which is a kind error: MayFail a is not a type because MayFail takes two arguments.
Similarly, if we tried
instance Functor (MayFail x y) where ...
then fmap would end up having the type
fmap :: (a -> b) -> MayFail x y a -> MayFail x y b
which is also a kind error: MayFail only takes two arguments, not three.
The only way to form a sensible type signature is to set f = MayFail e, because then f a becomes MayFail e a (and f b becomes MayFail e b), which is well-formed.
I'm doing exercises from the book "Programming in Haskell (2nd Edition)" and I have some problems in understanding the following:
"Given the following type of expressions
data Expr a = Var a | Val Int | Add (Expr a) (Expr a)
deriving Show
that contain variables of some type a, show how to make this type into instances of the Functor, Applicative and Monad classes. With the aid of an example, explain what the >>= operator for this type does."
I found a solution to the first question, which is the same as here: https://github.com/evturn/programming-in-haskell/blob/master/12-monads-and-more/12.05-exercises.hs (ex. 7), that is type correct.
The problem is that I cannot find out the sense of this exercise and the meaning of what this solution actually does.
To understand the solution, you need to get an intuition over a Functor, an Applicative and a Monad.
That being said fmap, <*> and >>= is just a way for one to be able to transform a data within an arbitrary F in your case that's an Expr from a -> b
Take a look at the Type class definitions of Functor, Applicative and Monad for example.
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
<*> :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
>>= :: m a -> (a -> m b) -> m b
Though on the bigger picture, these functions also execute effects of the algebraic datatype that have the type class instances for it.
For example, I will provide the rough definition of the Maybe monad.
instance Monad Maybe where
(Just something) >>= f = f something
Nothing >>= _ = Nothing
In this context, the bind or >>= combinator returns Nothing if there is Nothing for the input else it applies the arbitrary f on something such that f is a transformation from a -> Maybe b which satisfies the definition of the >>= combinator which is m a -> (a -> m b) -> m b where m is the Maybe datatype.
I've got a type t that supports the following three operations:
extract :: t a -> a
duplicate :: t a -> t (t a)
(<*>) :: t (a -> b) -> t a -> t b
Naturally I can also write bind:
(>>=) :: f a -> (a -> f b) -> f b
(>>=) x f = f (extract x)
And join:
join :: t (t a) -> t a
join = extract
But I can't write fmap nor pure
So this is kind of a "monad", and kind of a "comonad", but without fmap.
Technically, I have got an fmap and pure, but they're constrained.
I looked at various constrained functor style packages, but they all seem to constrain (<*>) as well, but in my case (<*>) is not constrained.
Is there an existing typeclass I could squeeze this type into?
If anyone is interested, the actual type I'm dealing with is the Closure type
Suppose I have a type T a b and I want to write an instance declarations e.g. an instance declaration for Functor that ranges over a and not b. Is this possible without defining a newtype?
I read What is the rule of the order of multiple type variables in haskell? which leads me to believe that this is not possible, but this seems completely arbitrary to me.
What I'm hoping for is something like:
instance Functor (T * b)
It's not arbitrary. It's how Hindley-Milner type inference works with higher-kinded types and curried type constructor application. Unification of type variables is based on the concept of generative type constructors. That is, if (f a) ~ (g b), then f ~ g and a ~ b, where ~ is type equality.
Let's apply that to unification of an expression like (fmap f someT), for someT :: T a b. I'll start by giving everything other than someT fresh type variables, to work the way unification does.
someT :: T a b
fmap :: (c -> d) -> f c -> f d
f :: e
By the fact that fmap is provided f as a first argument, we unify (c -> d) ~ e. So..
fmap f :: f c -> f d
someT :: T a b
This is where generativity comes into it. From here, we see (f c) ~ (T a b). Let me add some additional parenthesis for clarity: (f c) ~ ((T a) b). This is how type constructors work in Haskell - they are curried in the same way as term-level functions. By generativity, f ~ (T a) and c ~ b.
Then from that:
fmap f someT :: T a d
So it's necessarily true that the Functor instance must operate only on the second type argument of the type T.
Of course this all goes back to the type inference algorithm. You could give up Hindley-Milner or curried type constructors to make things work differently. But the result would be very different from Haskell in far more ways than just allowing a couple instances that Haskell doesn't.
In Haskell, a type constructor can take a type argument, of course.
A function a -> b, when looked at as a "type with a funny constructor name", has type (->) a b. That makes it a type constructor (->) with two arguments, a and b. This is frequently encountered in the "reader" pattern as in its Functor and Applicative instances:
instance Functor ((->) a) where
fmap = (.)
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
When I first tried to understand uses of this instance, as in
fmap (+1) (*2) 3 (=== (+1) . (*2) $ 3 === 3*2+1 === 7)
my reaction was "Ok, (+1) has type Int -> Int, which is (->) Int Int, so that matches Functor.... but where is the Int? I make a Maybe Int by calling Just 1, but I don't ever make a (->) Int Int by applying anything to an Int. In fact, I destroy a ((->) Int Int) by applying it to an Int! (Yeah, there's Nothing, but that seems... degenerate.)"
This all works (of course), as long as I remember that just because a type is built from a constructor+argument, that doesn't mean its values are built from a correspondingly typed constructor+argument. And some of the most interesting and powerful (and tricky to understand) type constructors are like this ((->), Lens, Arrow, etc)
(OK, really it's Num a => a, not Int, but let's ignore that, not relevant)
Is there a name for this concept? What is the appropriate mental model for thinking about type constructors, without leaning on the misleading and disempowering crutch interpretation "Foo a is a structure Foo containing value(s) of type a)?
This concept is known as a contravariant functor, on in Haskell-speak a Contravariant type.
class Contravariant f where
contramap :: (b -> a) -> f a -> f b
-- compare
class Functor f where
fmap :: (a -> b) -> f a -> f b
More generally, we can think of type variables in a type as having contravariant or covariant nature (at its simplest). For instance, by default we have
newtype Reader t a = Reader (t -> a)
instance Functor (Reader t) where
fmap ab (Reader ta) = Reader (ab . ta)
Which indicates that the second type parameter to Reader is covariant, while if we reverse the order
newtype RevReader a t = RevReader (t -> a)
instance Contravariant (RevReader a) where
contramap st (RevReader ta) = RevReader (ta . st)
A useful intuition for Contravariant types is that they have the ability to consume zero, one, or many values of the contravariant parameter instead of containing zero, one, or many values of the covariant parameter like we often think of when considering Functors.
Combining these two notions is the Profunctor
class Profunctor p where
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
which, as we notice, demands that p is of kind * -> * -> * where the first type parameter is contravariant and the second covariant. This class well characterizes the (->) type constructor
instance Profuntor (->) where
dimap f g h = g . h . f
Again, if we think of contravariant type parameters as being consumed and covariant ones as being produced this is quite amenable of the typical intuition around (->) types.
A few more examples of types which contravariant parameters include Relation
newtype Relation t = Relation (t -> t -> Bool)
instance Contravariant Relation where
contramap g (Relation pred) = Relation $ \a b -> pred (g a) (g b)
Or Fold which represents a left fold as a data type
newtype Fold a b = Fold b (a -> Fold a b)
instance Profunctor Fold where
dimap f g (Fold b go) = Fold (g b) (go . f)
sumF :: Num a => Fold a a
sumF = go 0 where
go n = Fold n (\i -> go (n + i))
With Fold a b we see that it consumes an arbitrary number of a types to produce one b type.
Generally what we find is that while it's often the case that we have covariant and "container" (strictly positive) types where values of some type c a are produced from a constructor of type a -> c a and some filler values a, in general that doesn't hold. In particular we have covariant types like that, but also contravariant ones which are often processes which somehow consume values of their parameterized type variables, or even more exotic ones like phantom types which utterly ignore their type variables
newtype Proxy a = Proxy -- need no `a`, produce no `a`
-- we have both this instance
instance Functor Proxy where
fmap _ Proxy = Proxy
-- and this one, though both instances ignore the passed function
instance Contravariant Proxy where
contramap _ Proxy = Proxy
and... "nothing special" type variables which cannot have any sort of nature, usually because they're being used as both covariant and contravariant types.
data Endo a = Endo (a -> a)
-- no instance Functor Endo or Contravariant Endo, it needs to treat
-- the input `a` differently from the output `a` such as in
--
-- instance Profunctor (->) where
Finally, a type constructor which takes multiple arguments may have different natures for each argument. In Haskell, the final type parameter is usually treated specially, though.