I think there is a type mismatch in default definition in instance Applicative Maybe in Haskell - haskell

I am currently studying Haskell with Prof. Hutton's "Programming in Haskell", and I found something strange regarding the definition of Maybe as an instance of the class Applicative.
In GHC.Base, the instance Applicative Maybe is defined as follows:
instance Applicative Maybe where
pure = Just
Just f <*> m = fmap f m
Nothing <*> _m = Nothing
It is the line which defines the value of Nothing <\*> _ as Nothing that bothers me. Nothing is of type Maybe a, where the operator <*> actually requires f (a -> b) (in this case, Maybe (a -> b)) as its first argument's type. Therefore, this is a type mismatch, which Haskell should complain about. However, this is accepted as a default definition, and therefore Haskell does not complain about it where I think it should.
What am I missing?

The a in Maybe a is a type variable, and can be any type at all! So Nothing can have the type Maybe Int, or Maybe [x], or Maybe (p -> q), for example.
Don't get confused by the fact that the variable name a is used in two places. The a in the type of Nothing is a completely different variable from the a in the type of <*>, and just happens to have the same name!
(That's exactly the same as if you wrote f x = x + 5 and then elsewhere, g x = "Hello, " ++ x. The use of x in both places doesn't matter, because they are in different scopes. Same with the a in this types. Different scopes, so they are different variables.)

Let's make things clearer by relabeling a type variable:
Nothing :: Maybe x
The type Maybe x unifies with Maybe (a -> b), with x ~ (a -> b). That is, Nothing is a value that can used as Maybe a for any a, including a function type. Thus it is a legal left-hand argument for <*> here.

Related

What's the meaning of `fmap` over set of predicates in Haskell?

My student assignment I'm doing for Haskell programming includes a task I'm a little bit puzzled to solve. The things are given so: an instance of Functor class to be created just for a set-based new type. There is a declaration of that:
newtype Set x = Set { contains :: (x -> Bool) }
It's a case for me to understand what means if fmap serves to be applied to something like a set of predicates. When doing about previous tasks, I've already defined fmap rather with functions like (+3) (to alter integers), (toUpper) (to strings) etc. It's first time I'm dealing with anything beyond normal types (various numerics, String, Char). There is my humble attempt to start:
instance Functor Set where
fmap f (Set x) = if (contains x) == True then Set (f x) else Set x
Surely, it's a nonsense code, but I suppose some True/False need to be evaluated before fmap apllication goes well. But, first of all, would you please explain the matter of set of predicates to elaborate more sensible approach?
With this definition, it is actually impossible to define a Functor instance for Set. The reason for this is that your Set a type contains a in a negative position... that is, a is an argument to a function, not a value. When that happens, the type constructor can be a contravariant functor (type class Contravariant from the contravariant package), but it cannot be a covariant functor (the Functor type class).
Here's are definitions of those classes:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
See the difference? In a contravariant functor, the direction of the function you pass in is flipped when it's lifted to operate on the functor type.
In the end, this should make sense. Your notion of a "set" is a test that tells you whether something qualifies or not. This is a perfectly good mathematical definition of a set, but it gives you different computational powers than the standard one. For example, you cannot get at the elements of your predicate-based sets; only wait to be given a potential element. If you have a Set Integer, and a function f :: String -> Integer, then you can test Strings by first converting them to Integers and testing those, so you can get from Set Integer to Set String. But having a g :: Integer -> String doesn't let you test Strings!
If this is an assignment, then either you've misunderstood the assignment, you've done some earlier step differently than expected (e.g., if you defined Set yourself in an earlier part, maybe you need to change the definition), or perhaps your instructor is hoping you'll struggle with this and understand why Functor cannot be defined.

Code unexpectedly accepted by GHC/GHCi

I don't understand why this code should pass type-checking:
foo :: (Maybe a, Maybe b)
foo = let x = Nothing in (x,x)
Since each component is bound to the same variable x, I would expect that the most general type for this expression to be (Maybe a, Maybe a). I get the same results if I use a where instead of a let. Am I missing something?
Briefly put, the type of x gets generalized by let. This is a key step in the Hindley-Milner type inference algorithm.
Concretely, let x = Nothing initially assigns x the type Maybe t, where t is a fresh type variable. Then, the type gets generalized, universally quantifying all its type variables (technically: except those in use elsewhere, but here we only have t). This causes x :: forall t. Maybe t. Note that this is exactly the same type as Nothing :: forall t. Maybe t.
Hence, each time we use x in our code, that refers to a potentially different type Maybe t, much like Nothing. Using (x, x) gets the same type as (Nothing, Nothing) for this reason.
Instead, lambdas do not feature the same generalization step. By comparison (\x -> (x, x)) Nothing "only" has type forall t. (Maybe t, Maybe t), where both components are forced to be of the same type. Here x is again assigned type Maybe t, with t fresh, but it is not generalized. Then (x, x) is assigned type (Maybe t, Maybe t). Only at the top-level we generalize adding forall t, but at that point is too late to obtain a heterogeneous pair.

Partially applying a type in a type constructor

In the book "Learn you a Haskell", chapter 11 we have the introduction of the newtype keyword and it all makes sense to me up to the part where we see the Pair type being made an instance of a Functor.
This discussion begins with a problem statement that "only type constructors that take exactly one parameter can be made an instance of Functor." I don't understand this statement. Where is this restriction ever described?
In the context of the discussion we have a type Pair defined as:
newtype Pair b a = Pair { getPair :: (a,b) }
Given this, I would have thought that we could have used something like:
instance Functor (Pair a b) where ...
I would have thought that (Pair a b) would have substituted for 'f' in the definition of Functor without any problem. What keeps this from working?
Next, the author goes on to make Pair an instance of a Functor using the following:
instance Functor (Pair c) where ...
Here is where I get lost. I don't recall ever seeing 'partially applying' types to a type constructor before. I am not really sure what this even means in this context, let alone how it solves the problem identified above it.
I think I have a misconception somewhere but I don't know where to go looking for it. I did find this answer but it only seems to go part of the way in answering the question.
"only type constructors that take exactly one parameter can be made an instance of Functor." I don't understand this statement. Where is this restriction ever described?
The restriction comes from the type of fmap in the definition of Functor:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Because the class variable f is applied to one argument in f a, the type used to instantiate Functor must be able to take one parameter. Because the application f a is part of a function type, f must not take more than one parameter. (There's one more subtle piece about what kinds of arguments f can take that's specified here, but I think it's worth skipping that for now; hopefully your tutorial will touch on this subtlety more later.)
Given this, I would have thought that we could have used something like:
instance Functor (Pair a b) where ...
I would have thought that (Pair a b) would have substituted for 'f' in the definition of Functor without any problem. What keeps this from working?
It is once again the type of fmap that keeps this from working. Filling in Pair c d for f (modifying a to c and b to d to avoid name clashes), we would get
fmap :: (a -> b) -> Pair c d a -> Pair c d b
which doesn't make a lot of sense.
Here is where I get lost. I don't recall ever seeing 'partially applying' types to a type constructor before.
Well... now you have. =)
I am not really sure what this even means in this context, let alone how it solves the problem identified above it.
It means basically the same thing partial application at the term level means: Pair a is akin to a type function which takes another type as an argument. So, e.g., Pair a applied to Int would give the Pair a Int type. It solves the problem because now we are supplying a "type-function-like" thing rather than a "type-like" thing, so applying it to another type makes sense; that is, the substituted type of fmap for a Pair c instance would be
fmap :: (a -> b) -> Pair c a -> Pair c b
which now makes sense because Pair c a and Pair c b are sensible types, whereas before Pair c d a and Pair c d b were over-applied and therefore not sensible types.

Any advantage of using type constructors in type classes?

Take for example the class Functor:
class Functor a
instance Functor Maybe
Here Maybe is a type constructor.
But we can do this in two other ways:
Firstly, using multi-parameter type classes:
class MultiFunctor a e
instance MultiFunctor (Maybe a) a
Secondly using type families:
class MonoFunctor a
instance MonoFunctor (Maybe a)
type family Element
type instance Element (Maybe a) a
Now there's one obvious advantage of the two latter methods, namely that it allows us to do things like this:
instance Text Char
Or:
instance Text
type instance Element Text Char
So we can work with monomorphic containers.
The second advantage is that we can make instances of types that don't have the type parameter as the final parameter. Lets say we make an Either style type but put the types the wrong way around:
data Silly t errorT = Silly t errorT
instance Functor Silly -- oh no we can't do this without a newtype wrapper
Whereas
instance MultiFunctor (Silly t errorT) t
works fine and
instance MonoFunctor (Silly t errorT)
type instance Element (Silly t errorT) t
is also good.
Given these flexibility advantages of only using complete types (not type signatures) in type class definitions, is there any reason to use the original style definition, assuming you're using GHC and don't mind using the extensions? That is, is there anything special you can do putting a type constructor, not just a full type in a type class that you can't do with multi-parameter type classes or type families?
Your proposals ignore some rather important details about the existing Functor definition because you didn't work through the details of writing out what would happen with the class's member function.
class MultiFunctor a e where
mfmap :: (e -> ??) -> a -> ????
instance MultiFunctor (Maybe a) a where
mfmap = ???????
An important property of fmap at the moment is that its first argument can change types. fmap show :: (Functor f, Show a) => f a -> f String. You can't just throw that away, or you lose most of the value of fmap. So really, MultiFunctor would need to look more like...
class MultiFunctor s t a b | s -> a, t -> b, s b -> t, t a -> s where
mfmap :: (a -> b) -> s -> t
instance (a ~ c, b ~ d) => MultiFunctor (Maybe a) (Maybe b) c d where
mfmap _ Nothing = Nothing
mfmap f (Just a) = Just (f a)
Note just how incredibly complicated this has become to try to make inference at least close to possible. All the functional dependencies are in place to allow instance selection without annotating types all over the place. (I may have missed a couple possible functional dependencies in there!) The instance itself grew some crazy type equality constraints to allow instance selection to be more reliable. And the worst part is - this still has worse properties for reasoning than fmap does.
Supposing my previous instance didn't exist, I could write an instance like this:
instance MultiFunctor (Maybe Int) (Maybe Int) Int Int where
mfmap _ Nothing = Nothing
mfmap f (Just a) = Just (if f a == a then a else f a * 2)
This is broken, of course - but it's broken in a new way that wasn't even possible before. A really important part of the definition of Functor is that the types a and b in fmap don't appear anywhere in the instance definition. Just looking at the class is enough to tell the programmer that the behavior of fmap cannot depend on the types a and b. You get that guarantee for free. You don't need to trust that instances were written correctly.
Because fmap gives you that guarantee for free, you don't even need to check both Functor laws when defining an instance. It's sufficient to check the law fmap id x == x. The second law comes along for free when the first law is proven. But with that broken mfmap I just provided, mfmap id x == x is true, even though the second law is not.
As the implementer of mfmap, you have more work to do to prove your implementation is correct. As a user of it, you have to put more trust in the implementation's correctness, since the type system can't guarantee as much.
If you work out more complete examples for the other systems, you find that they have just as many issues if you want to support the full functionality of fmap. And this is why they aren't really used. They add a lot of complexity for only a small gain in utility.
Well, for one thing the traditional functor class is just much simpler. That alone is a valid reason to prefer it, even though this is Haskell and not Python. And it also represents the mathematical idea better of what a functor is supposed to be: a mapping from objects to objects (f :: *->*), with extra property (->Constraint) that each (forall (a::*) (b::*)) morphism (a->b) is lifted to a morphism on the corresponding object mapped to (-> f a->f b). None of that can be seen very clearly in the * -> * -> Constraint version of the class, or its TypeFamilies equivalent.
On a more practical account, yes, there are also things you can only do with the (*->*)->Constraint version.
In particular, what this constraint guarantees you right away is that all Haskell types are valid objects you can put into the functor, whereas for MultiFunctor you need to check every possible contained type, one by one. Sometimes that's just not possible (or is it?), like when you're mapping over infinitely many types:
data Tough f a = Doable (f a)
| Tough (f (Tough f (a, a)))
instance (Applicative f) = Semigroup (Tough f a) where
Doable x <> Doable y = Tough . Doable $ (,)<$>x<*>y
Tough xs <> Tough ys = Tough $ xs <> ys
-- The following actually violates the semigroup associativity law. Hardly matters here I suppose...
xs <> Doable y = xs <> Tough (Doable $ fmap twice y)
Doable x <> ys = Tough (Doable $ fmap twice x) <> ys
twice x = (x,x)
Note that this uses the Applicative instance of f not just on the a type, but also on arbitrary tuples thereof. I can't see how you could express that with a MultiParamTypeClasses- or TypeFamilies-based applicative class. (It might be possible if you make Tough a suitable GADT, but without that... probably not.)
BTW, this example is perhaps not as useless as it may look – it basically expresses read-only vectors of length 2n in a monadic state.
The expanded variant is indeed more flexible. It was used e.g. by Oleg Kiselyov to define restricted monads. Roughly, you can have
class MN2 m a where
ret2 :: a -> m a
class (MN2 m a, MN2 m b) => MN3 m a b where
bind2 :: m a -> (a -> m b) -> m b
allowing monad instances to be parametrized over a and b. This is useful because you can restrict those types to members of some other class:
import Data.Set as Set
instance MN2 Set.Set a where
-- does not require Ord
return = Set.singleton
instance Prelude.Ord b => MN3 SMPlus a b where
-- Set.union requires Ord
m >>= f = Set.fold (Set.union . f) Set.empty m
Note than because of that Ord constraint, we are unable to define Monad Set.Set using unrestricted monads. Indeed, the monad class requires the monad to be usable at all types.
Also see: parameterized (indexed) monad.

Why does the Applicative instance for Maybe give Nothing when function is Nothing in <*>

I am a beginner with haskell and am reading the Learn you a haskell book. I have been trying to digest functors and applicative functors for a while now.
In the applicative functors topic, the instance implementation for Maybe is given as
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
So, as I understand it, we get Nothing if the left side functor (for <*>) is Nothing. To me, it seems to make more sense as
Nothing <*> something = something
So that this applicative functor has no effect. What is the usecase, if any for giving out Nothing?
Say, I have a Maybe String with me, whose value I don't know. I have to give this Maybe to a third party function, but want its result to go through a few Maybe (a -> b)'s first. If some of these functions are Nothing I'll want them to silently return their input, not give out a Nothing, which is loss of data.
So, what is the thinking behind returning Nothing in the above instance?
How would that work? Here's the type signature:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
So the second argument here would be of type Maybe a, while the result needs to be of type Maybe b. You need some way to turn a into b, which you can only do if the first argument isn't Nothing.
The only way something like this would work is if you have one or more values of type Maybe (a -> a) and want to apply any that aren't Nothing. But that's much too specific for the general definition of (<*>).
Edit: Since it seems to be the Maybe (a -> a) scenario you actually care about, here's a couple examples of what you can do with a bunch of values of that type:
Keeping all the functions and discard the Nothings, then apply them:
applyJust :: [Maybe (a -> a)] -> a -> a
applyJust = foldr (.) id . catMaybes
The catMaybes function gives you a list containing only the Just values, then the foldr composes them all together, starting from the identity function (which is what you'll get if there are no functions to apply).
Alternatively, you can take functions until finding a Nothing, then bail out:
applyWhileJust :: [Maybe (a -> a)] -> a -> a
applyWhileJust (Just f:fs) = f . applyWhileJust fs
applyWhileJust (Nothing:_) = id
This uses a similar idea as the above, except that when it finds Nothing it ignores the rest of the list. If you like, you can also write it as applyWhileJust = foldr (maybe (const id) (.)) id but that's a little harder to read...
Think of the <*> as the normal * operator. a * 0 == 0, right? It doesn't matter what a is. So using the same logic, Just (const a) <*> Nothing == Nothing. The Applicative laws dictate that a data type has to behave like this.
The reason why this is useful, is that Maybe is supposed to represent the presence of something, not the absence of something. If you pipeline a Maybe value through a chain of functions, if one function fails, it means that a failure happened, and that the process needs to be aborted.
The behavior you propose is impractical, because there are numerous problems with it:
If a failed function is to return its input, it has to have type a -> a, because the returned value and the input value have to have the same type for them to be interchangeable depending on the outcome of the function
According to your logic, what happens if you have Just (const 2) <*> Just 5? How can the behavior in this case be made consistent with the Nothing case?
See also the Applicative laws.
EDIT: fixed code typos, and again
Well what about this?
Just id <*> Just something
The usecase for Nothing comes when you start using <*> to plumb through functions with multiple inputs.
(-) <$> readInt "foo" <*> readInt "3"
Assuming you have a function readInt :: String -> Maybe Int, this will turn into:
(-) <$> Nothing <*> Just 3
<$> is just fmap, and fmap f Nothing is Nothing, so it reduces to:
Nothing <*> Just 3
Can you see now why this should produce Nothing? The original meaning of the expression was to subtract two numbers, but since we failed to produce a partially-applied function after the first input, we need to propagate that failure instead of just making up a nice function that has nothing to do with subtraction.
Additional to C. A. McCann's excellent answer I'd like to point out that this might be a case of a "theorem for free", see http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf . The gist of this paper is that for some polymorphic functions there is only one possible implementiation for a given type signature, e.g. fst :: (a,b) -> a has no other choice than returning the first element of the pair (or be undefined), and this can be proven. This property may seem counter-intuitive but is rooted in the very limited information a function has about its polymorphic arguments (especially it can't create one out of thin air).

Resources