What is the Maybe type and how does it work? - haskell

I am just starting to program in Haskell, and I came across the following definition:
calculate :: Float -> Float -> Maybe Float

Maybe a is an ordinary data type defined as:
data Maybe a = Just a | Nothing
There are thus two possibilities: or you define a value of type a as Just a (like Just 3), or Nothing in case the query has no answer.
It is meant to be defined as a way to define output for non-total functions.
For instance: say you want to define sqrt. The square root is only defined for positive integers, you can thus define sqrt as:
sqrt x | x >= 0 = Just $ ...
| otherwise = Nothing
with ... a way to calculate the square root for x.
Some people compare Nothing with the "null pointer" you find in most programming languages. By default, you don't implement a null pointer for data types you define (and if you do, all these "nulls" look different), by adding Nothing you have a generic null pointer.
It can thus be useful to use Maybe to denote that it is possible no output can be calculated. You could of course also error on values less than 0:
sqrt x | x >= 0 = Just $ ...
| otherwise = error "The value must be larger or equal to 0"
But errors usually are not mentioned in the type signature, nor does a compiler have any problem if you don't take them into account. Haskell is also shifting to total functions: it's better to always try at least to return a value (e.g. Nothing) for all possible inputs.
If you later want to use the result of a Maybe a, you for instance need to write:
succMaybe :: Maybe Int -> Maybe Int
succMaybe (Just x) = Just (x+1)
succMaybe _ = Nothing
But by writing Just for the first case, you somehow warn yourself that it is possible that Nothing can occur. You can also get rid of the Maybe by introducing a "default" value:
justOrDefault :: a -> Maybe a -> a
justOrDefault _ (Just x) = x
justOrDefault d _ = d
The builtin maybe function (note the lowercase), combines the two previous functions:
maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe z _ Nothing = z
So you specify a b (default value) together with a function (a -> b). In case Maybe a is Just x, the function is applied to it and returned, in case the input value is Nothing, the default value will be used.
Working with Maybe a's can be hard, because you always need to take the Nothing case into account, to simplify this you can use the Maybe monad.
Tom Schrijvers also shows that Maybe is the successor function in type algebra: you add one extra value to your type (Either is addition and (,) is the type-algebraic equivalent of multiplication).

Related

Can't understand a simple Haskell function?

Can someone explain to me step by step what this function means?
select :: (a->a->Bool) -> a -> a -> a
As the comments pointed out, this is not a function definition, but just a type signature. It says, for any type a which you are free to choose, this function expects:
A function that takes two values of type a and gives a Bool
Two values of type a
and it returns another value of type a. So for example, we could call:
select (<) 1 2
where a is Int, since (<) is a function that takes two Ints and returns a Bool. We could not call:
select isPrefixOf 1 2
because isPrefixOf :: (Eq a) => [a] -> [a] -> Bool -- i.e. it takes two lists (provided that the element type supports Equality), but numbers are not lists.
Signatures can tell us quite a lot, however, due to parametericity (aka free theorems). The details are quite techincal, but we can intuit that select must return one of its two arguments, because it has no other way to construct values of type a about which it knows nothing (and this can be proven).
But beyond that we can't really tell. Often you can tell almost certainly what a function does by its signature. But as I explored this signature, I found that there were actually quite a few functions it could be, from the most obvious:
select f x y = if f x y then x else y
to some rather exotic
select f x y = if f x x && f y y then x else y
And the name select doesn't help much -- it seems to tell us that it will return one of the two arguments, but the signature already told us that.

Haskell: function to find out by type definition

Also owing to all your help, I made some steps in understanding the type system in Haskell. What I still don't understand is a construction like this:
chk :: Eq b => (a -> b) -> a -> b -> Bool
Why is the class constraint only on 'b', while you cannot compare different types?
Isn't a/b used to indicate different types anyway?
If I got this all wrong, can you show me a function that would typecheck like that?
Such a function would only be able to compare two values of type b for equality, no as involved.
If you look at the type, there is one implementation that seems to be the obvious one:
chk :: Eq b => (a -> b) -> a -> b -> Bool
chk f x y =
let z = f x -- z :: b
in y == z -- comparison of two values of type b
You need to clearly separate in your mind the difference between type variables and normal variables.
The type (Eq b) =>... means that b can be any type, provided that values of that type are comparable. So b = Int would work, because we can compare Int values (e.g., 3 == 5 is false, but 2 == 2 is true). But b = IO Int would not work, since you cannot compare I/O operations for equality.
All of this has nothing to do with whether a == b; both a and b are types, not values. The type says that a can be any type, and b can also be any type (if it implements Eq). In particular, it's possible for a and b to be the same type, but it's also possible for them to be different types. Using different type variables says that these can be different types, not that they must be different.
Ler's see how we could deduce a sensible implementation of chk from its type.
Having two values, one of type a and one of type b, we can't do much with them. Both types are unknown. (They may be in fact the same type but we don't know that). We know we can compare two values of type b for equality, but there's only one such value at our disposal. We can compare it with itself but this doesn't make much sense. If we had another value of type b, we could compare the two.
But there are three arguments, one of type a, one of type b, and one is a function of type a->b. The only other thing we can do with them (apart from comparing a value with itself) is to apply the function to the value of type a. The result of this application has type b. But wait, this is exactly what we wanted, another value of type b to complete the comparison. And since the result of the comparison is of type Bool, this is exactly what we need to complete chk.
chk f x y = f x == y
And this is the one of two non-trivial ways to write this function. The other one replaces == with /=.
There are in fact a very limited amount of functions of this type and we can enumerate them all. If you only take into account total functions and require that equality is reflexive and symmetric, then there are only two other functions of this type:
chk0 f x y = True
chk1 f x y = False
If you drop these restrictions, you can write also:
chk2 f x y = undefined
chk3 f x y = y == y // may be different from just True
chk4 f x y = f x == f x
and perhaps a dozen more.

First time using the Maybe type in Haskell, is my understanding wrong?

From my understanding, the Maybe type is something you can combine with another type. It lets you specify a condition for the inputs that you combined it with using the "Just... Nothing" format.
an example from my lecture slides is a function in Haskell that gives the square root of an input, but before doing so, checks to see if the input is positive.:
maybe_sqrt :: Maybe Float -> Maybe Float
maybe_sqrt maybe_x = case maybe_x of
Just x
| x >= 0 -> Just (sqrt x)
| otherwise -> Nothing
Nothing -> Nothing
However, I don't understand why this function uses both cases and guards. Why can't you just use guards, like this?:
maybe_sqrt :: Maybe Float -> Maybe Float
maybe_sqrt x
| x >= 0 = Just (sqrt x)
| otherwise = Nothing
the Maybe type is something you can combine with another type
Maybe is not a type†. It's a type constructor, i.e. you can use it to generate a type. For instance, Maybe Float is a type, but it's a different type from Float as such. A Maybe Float can not be used as a Float because, well, maybe it doesn't contain one!
But to calculate the square root, you need a Float. Well, no problem: in the Just case, you can just unwrap it by pattern matching! But pattern matching automatically prevents you from trying to unwrap a Float out of a Nothing value, which, well, doesn't contain a float which you could compare to anything.
Incidentally, this does not mean you to need trace every possible failure by pattern matching, all the way through your code. Luckily, Maybe is a monad. This means, if your function was a Kleisli arrow
maybe_sqrt :: Float -> Maybe Float
maybe_sqrt x
| x >= 0 = Just (sqrt x)
| otherwise = Nothing
(which is fine because it does accept a plain float) then you can still use this very easily with a Maybe Float as the argument:
GHCi> maybe_sqrt =<< Just 4
Just 2.0
GHCi> maybe_sqrt =<< Just (-1)
Nothing
GHCi> maybe_sqrt =<< Nothing
Nothing
†As discussed in the comments, there is some disagreement on whether we should nevertheless call Maybe type, or merely a type-level entity. As per research by Luis Casillas, it's actually rather Ok to call it a type. Anyway: my point was that Maybe Float is not “an OR-combination of the Maybe type (giving failure) and the Float type (giving values)”, but a completely new type with the structure of Maybe a and the optionally-contained elements of Float.
If your type were maybe_sqrt :: Float -> Maybe Float then that is how you would do it.
As it is, consider: what should your function do if your input is Nothing? Probably, you would want to return Nothing -- but why should your compiler know that?
The whole point of an "option" type like Maybe is that you can't ignore it -- you are required to handle all cases. If you want your Nothing cases to fall through to a Nothing output, Haskell provides a (somewhat) convenient facility for this:
maybe_sqrt x_in = do
x <- x_in
if x >= 0 then return sqrt x
else Nothing
This is the Maybe instance of Monad, and it does what you probably want. Any time you have a Maybe T expression, you can extract only the successful Just case with pattern <- expression. The only thing to remember is that non-Maybe bindings should use let pattern = expression instead.
This is more an extended comment than an answer. As leftaroundabout indicated, Maybe is an instance of Monad. It's also an instance of Alternative. You can use this fact to implement your function, if you like:
maybe_sqrt :: Maybe Float -> Maybe Float
maybe_sqrt maybe_x = do
x <- maybe_x
guard (x >= 0)
pure (sqrt x)
This is also more an extended comment (if this is your first time working with Maybe, you may not have encountered type classes yet; come back when you do). As others already said, x has type Maybe Float. But writing x >= 0 doesn't require x to be Float. What does it actually require? >= has type (Ord a) => a -> a -> Bool, which means it works for any types which are instances of Ord type class (and Maybe Float is one), and both arguments must have the same type. So 0 must be a Maybe Float as well! Haskell actually allows this, if Maybe Float belongs to the Num type class: which it doesn't in the standard library, but you could define an instance yourself:
instance Num a => Num (Maybe a) where
fromInteger x = Just (fromInteger x)
# this means 0 :: Maybe Float is Just 0.0
negate (Just x) = Just (negate x)
negate Nothing = Nothing
Just x + Just y = Just (x + y)
_ + _ = Nothing
# or simpler:
# negate = fmap negate
# (+) = liftA2 (+)
# similar for all remaining two argument functions
...
Now x >= 0 is meaningful. sqrt x is not; you'll need instances for Floating and Fractional as well. Of course, Just (sqrt x) will be Maybe (Maybe a), not Maybe a! But just sqrt x will do what you want.
The problem is that it works kind of by coincidence that Nothing >= 0 is False; if you checked x <= 0, Nothing would pass.
Also, it's generally a bad idea to define "orphan instances": i.e. the instance above should really only be defined in the module defining Maybe or in the module defining Num.

Haskell - Maybe Either

-- | Convert a 'Maybe a' to an equivalent 'Either () a'. Should be inverse
-- to 'eitherUnitToMaybe'.
maybeToEitherUnit :: Maybe a -> Either () a
maybeToEitherUnit a = error "Not yet implemented: maybeToEitherUnit"
-- | Convert a 'Either () a' to an equivalent 'Maybe a'. Should be inverse
-- to 'maybeToEitherUnit'.
eitherUnitToMaybe :: Either () a -> Maybe a
eitherUnitToMaybe = error "Not yet implemented: eitherUnitToMaybe"
-- | Convert a pair of a 'Bool' and an 'a' to 'Either a a'. Should be inverse
-- to 'eitherToPairWithBool'.
pairWithBoolToEither :: (Bool,a) -> Either a a
pairWithBoolToEither = undefined -- What should I do here?
-- | Convert an 'Either a a' to a pair of a 'Bool' and an 'a'. Should be inverse
-- to 'pairWithBoolToEither'.
eitherToPairWithBool :: Either a a -> (Bool,a)
eitherToPairWithBool = undefined -- What should I do here?
-- | Convert a function from 'Bool' to 'a' to a pair of 'a's. Should be inverse
-- to 'pairToFunctionFromBool'.
functionFromBoolToPair :: (Bool -> a) -> (a,a)
functionFromBoolToPair = error "Not yet implemented: functionFromBoolToPair"
-- | Convert a pair of 'a's to a function from 'Bool' to 'a'. Should be inverse
-- to 'functionFromBoolToPair'.
pairToFunctionFromBool :: (a,a) -> (Bool -> a)
pairToFunctionFromBool = error "Not yet implemented: pairToFunctionFromBool"
I don't really know what to do. I know what maybe is, but I think I have a problem with either, because Either a a makes no sense in my mind. Either a b would be okay. This is either a or b but Either a a is a?!
I don't have any idea in general how to write these functions.
Given that I think this is homework, I'll not answer, but give important hints:
If you look for the definitions on hoogle (http://www.haskell.org/hoogle/)
you find
data Bool = True | False
data Either a b = Left a | Right b
This means that Bool can only be True or False, but that Either a b can be Left a or Right b.
which means your functions should look like
pairWithBoolToEither :: (Bool,a) -> Either a a
pairWithBoolToEither (True,a) = ....
pairWithBoolToEither (False,a) = ....
and
eitherToPairWithBool :: Either a a -> (Bool,a)
eitherToPairWithBool (Left a) = ....
eitherToPairWithBool (Right a) = ....
Comparing with Maybe
Maybe a is given by
data Maybe a = Just a | Nothing
so something of type Maybe Int could be Just 7 or Nothing.
Similarly, something of type Either Int Char could be Left 5 or Right 'c'.
Something of type Either Int Int could be Left 7 or Right 4.
So something with type Either Int Char is either an Int or a Char, but something of type Either Int Int is either an Int or an Int. You don't get to choose anything other than Int, but you'll know whether it was a Left or a Right.
Why you've been asked this/thinking behind it
If you have something of type Either a a, then the data (eg 5 in Left 5) is always of type a, and you've just tagged it with Left or Right. If you have something of type (Bool,a) the a-data (eg 5 in (True,5)) is always the same type, and you've paired it with False or True.
The maths word for two things which perhaps look different but actually have the same content is "isomorphic". Your instructor has asked you to write a pair of functions which show this isomorphism. Your answer will go down better if pairWithBoolToEither . eitherToPairWithBool and eitherToPairWithBool . pairWithBoolToEither do what id does, i.e. don't change anything. In fact, I've just spotted the comments in your question, where it says they should be inverses. In your write-up, you should show this by doing tests in ghci like
ghci> eitherToPairWithBool . pairWithBoolToEither $ (True,'h')
(True,'h')
and the other way round.
(In case you haven't seen it, $ is defined by f $ x = f x but $ has really low precedence (infixr 0 $), so f . g $ x is (f . g) $ x which is just (f . g) x and . is function composition, so (f.g) x = f (g x). That was a lot of explanation to save one pair of brackets!)
Functions that take or return functions
This can be a bit mind blowing at first when you're not used to it.
functionFromBoolToPair :: (Bool -> a) -> (a,a)
The only thing you can pattern match a function with is just a variable like f, so we'll need to do something like
functionFromBoolToPair f = ...
but what can we do with that f? Well, the easiest thing to do with a function you're given is to apply it to a value. What value(s) can we use f on? Well f :: (Bool -> a) so it takes a Bool and gives you an a, so we can either do f True or f False, and they'll give us two (probably different) values of type a. Now that's handy, because we needed to a values, didn't we?
Next have a look at
pairToFunctionFromBool :: (a,a) -> (Bool -> a)
The pattern match we can do for the type (a,a) is something like (x,y) so we'll need
pairToFunctionFromBool (x,y) = ....
but how can we return a function (Bool -> a) on the right hand side?
There are two ways I think you'll find easiest. One is to notice that since -> is right associative anyway, the type (a,a) -> (Bool -> a) is the same as (a,a) -> Bool -> a so we can actually move the arguments for the function we want to return to before the = sign, like this:
pairToFunctionFromBool (x,y) True = ....
pairToFunctionFromBool (x,y) False = ....
Another way, which feels perhaps a little easier, would to make a let or where clause to define a function called something like f, where f :: Bool -> a< a bit like:
pairToFunctionFromBool (x,y) = f where
f True = ....
f False = ....
Have fun. Mess around.
Perhaps it's useful to note that Either a b is also called the coproduct, or sum, of the types a and b. Indeed it is now common to use
type (+) = Either
You can then write Either a b as a + b.
eitherToPairWithBool :: (a+a) -> (Bool,a)
Now common sense would dictate that we rewrite a + a as something like 2 ⋅ a. Believe it or not, that is exactly the meaning of the tuple type you're transforming to!
To explain: algebraic data types can roughly be seen as "counting1 the number of possible constructions". So
data Bool = True | False
has two constructors. So sort of (this is not valid Haskell!)
type 2 = Bool
Tuples allow all the combinations of constructors from each argument. So for instance in (Bool, Bool), we have the values
(False,False)
(False,True )
(True, False)
(True, True )
You've guessed it: tuples are also called products. So the type (Bool, a) is basically 2 ⋅ a: for every value x :: a, we can create both the (False, x) tuple and the (True, x) tuple, alltogether twice as many as there are x values.
Much the same thing for Either a a: we always have both Left x and Right x as a possible value.
All your functions with "arithmetic types":
type OnePlus = Maybe
maybeToEitherUnit :: OnePlus a -> () + a
eitherUnitToMaybe :: () + a -> OnePlus a
pairWithBoolToEither :: 2 ⋅ a -> a + a
eitherToPairWithBool :: a + a -> 2 ⋅ a
functionFromBoolToPair :: a² -> a⋅a
pairToFunctionFromBool :: a⋅a -> a²
1For pretty much any interesting type there are actually infinitely many possible values, still this kind of naïve arithmetic gets you surprisingly far.
Either a a makes no sense in my mind.
Yes it does. Try to figure out the difference between type a and Either a a. Either is a disjoint union. Once you understand the difference between a and Either a a, your homework should be easy in conjunction with AndrewC's answer.
Note that Either a b means quite literally that a value of such a type can be either an a, or an a. It sounds like you have actually grasped this concept, but the piece you're missing is that the Either type differentiates between values constructed with Left and those constructed with Right.
For the first part, the idea is that Maybe is either Just a thing or Nothing -- Nothing corresponds to () because both are "in essence" data types with only one possible value.
The idea behind converting (Bool, a) pairs to Either a a pairs might seem a little trickier, but just think about the correspondence between True and False and Left and Right.
As for converting functions of type (Bool -> a) to (a, a) pairs, here's a hint: Consider the fact that Bool can only have two types, and write down what that initial function argument might look like.
Hopefully those hints help you to get started.

Can fixed-point functions be used on polynomials?

I was thinking of a way to represent algebraic numbers in Haskell as a stream of approximations. You could probably do this by some root finding algorithm. But that's no fun. So you could add x to the polynomial, reducing the problem to finding it's fixed points.
So if you have a function in Haskell like
f :: Double -> Double
f x = x ^ 2 + x
I don't conceptually understand why fix doesn't work, which is to say, I can easily verify for myself that it doesn't work, but isn't 0 the true least fixed point of f? Is there another simple (as in definition size) fixed point function that would work?
Here is the implementation of the fix function:
fix :: (a -> a) -> a
fix f = let x = f x in x
It doesn't work for primitive types like Double. It's intended for types that have a more complex structure to them. For instance:
g :: Maybe Int -> Maybe Int
g i = Just $ case i of
Nothing -> 3
Just _ -> 4
This function will work with fix because it yields information about its result faster than it reads its input. in other words, the Just portion is known without looking at i at all, which enables it to reach a fixed point.
When your function is Double -> Double, and examines its input, fix won't work because there's no way to partially evaluate a Double.

Resources