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

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.

Related

Execution order of list comprehension filtering

Just started learning Haskell and came across this issue.
If I have a list comprehension with a condition such as
[x*2 | x<- [1..10], x `mod` 3 ==2]
I get
[4,10,16]
as expected. However, if I have instead
[x**2 | x<- [1..10], x `mod` 3 ==2]
It is has the type variable as ambiguous for the mod function. I presume this is because x2 promotes an integer to a float, but why does this affect the conditional? Why is the type ambiguous in this case? Does it calculate x2, and then square root it? (This seems highly improbable) Does it somehow keep track of the x that generated each x2 term?
Perhaps it's the imperative mindset, but internally, I thought the execution would be along the lines of [in python]
lst=[]
for x in range(10):
if x%3==2:
lst.append(x**2)
Could someone clarify/correct my understanding?
Let's have a look at the types of mod and (**):
mod :: Integral n => n -> n -> n
(**) :: Floating a => a -> a -> a
-- hm......
mod and (**) put other constraints on the used type. mod expects an integral type (Int, Integer), whereas (**) expects a floating type (Float, Double). Since there's no type that's both integral and a floating point number, GHC gives up.
Instead, use (^):
(^) :: (Integral n, Num a) => a -> n -> a
E.g.
[x ^ 2 | x <- [1..10], x `mod` 3 == 2]
By the way, you can find errors like this easier if you try to give a type to the result:
ghci> [x ** 2 | x <- [1..10], x `mod` 3 == 2] :: [Int]
<interactive>:1:4:
No instance for (Floating Int) arising from a use of `**'
In the expression: x ** 2
...
The first example works because of defaulting. The expression is inferred as having type
Integral a => [a]
and then the a type variable is defaulted to Integer for convenience.
In the second expression, the use of ** forces x to be Floating and the mod forces it to be Integral. So GHC infers that the expression has type
(Integral a, Floating a) => [a]
There is no standard numeric type that is both Integral and Floating, let alone one that participates in defaulting.
You mentioned the notion of numeric promotion in your question. C, C++, Java, and maybe some other languages have such a thing. Haskell does not, and those of us who use it tend to be grateful for that. All conversions from one numeric type to another have to be done using explicit conversion functions like fromIntegral, fromRational, round, floor, %, etc.
You probably meant to use ^ instead of **, which would leave just the Integral a constraint. In a real program, you should generally avoid the defaulting mechanism by including a type signature. You can turn it off altogether using
default ()
somewhere in your module.
List comprehension in haskell desugars to a do-block using the list monad. In your example, it would be something like:
x <- [1..10]
guard $ (x `mod` 3) == 2
return $ x**2
In this case it attempts to unify the types of (**) x 2 and mod x 3 which fails because you can't unify a Floating type with an Integral type without explicitly converting between the two.
You've got a few options: use (^^) instead of (**) or do ((fromIntegral x) ** 2) if you want x to be an integral type, or somehow round x to an integral type if you want it to be a floating type.

What is the Maybe type and how does it work?

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).

How can I have a function in haskell return either a boolean or a list of booleans?

I have function in haskell (lets call it 'dumb') which calls 3 different functions. These three different functions return different types, for example, a boolean or a list of booleans. How can I define function 'dumb' to either return a boolean or a list of booleans?
data Sumtype = givelist Integer | getprod Integer
prod :: Int -> Int
prod x = x*3
listnums :: Int -> [Int]
listnums x = [1...x]
dumb :: Sumtype -> (what comes here..?)
dumb (givelist x) -> listnums x
dum (getprod x) -> prod x
You make it return Either Boolean [Boolean]. But I'm suspicious about your motives. It sounds like an X/Y problem.
You're probably looking for the the Either type, although with it your function will return Either values. It's defined like this:
data Either a b = Left a | Right b
When you want to define a function that can return either a Bool or a list of Bools its type should look something like this:
dumb :: Either Bool [Bool]
In this case 'dumb' will be a function that doesn't take any arguments and return either a Bool or a list of Bools. In the function's body you can return a Bool like this:
Left bool
Or a list of bools like this:
Right [bool]
You can see a concrete example here: http://en.wikibooks.org/wiki/Haskell/More_on_datatypes#More_than_one_type_parameter
All that said though, the reason Sebastian asked you for more details is that Either is rarely used outside of error handling (AFAIK I know anyway). It's possible that in your case you don't really need it at all, but we can't be sure unless you tell us more about the other functions you use in 'dumb' and about your goals.
Unrelated Probems
It appears you are a beginner - welcome to Haskell! I strongly suggest you read and work through one of the many tutorials as that is more efficient and complete than asking individual questions.
Syntax
Let's start with correcting the syntax errors. Constructors, such as Givelist and Getprod must start with a capital letter. The function dumb was typo'ed once. Function definitions use = and not ->.
Types
Now we have type errors to address. The Sumtype uses Integer and you then switch to using Int. Lets just stick with Integer for simplicity.
With these fixes we get:
data Sumtype = Givelist Integer | Getprod Integer
prod :: Integer -> Integer
prod x = x*3
listnums :: Integer -> [Integer]
listnums x = [1...x]
dumb :: Sumtype -> (what comes here..?)
dumb (Givelist x) = listnums x
dumb (Getprod x) = prod x
The Question
You want to know "what comes here" where 'here' is the result type. As written, the function is actually invalid. One definition yields a list of integers, [Integer], while the other yields a single integer Integer. One solution is to use a sum type such as Either Integer [Integer] - this is very much like your pre-existing Sumtype:
dumb :: Sumtype -> Either Integer [Integer]
So now we need to return a constructor of Either in our function definitions. You can lookup the documentation or use :info Either in GHCi to learn the constructors if you don't have them memorized.
dumb (Givelist x) = Right (listnums x)
dumb (Getprod x) = Left (prod x)
Notice we had to use Left for the second case which returns an Integer, because the first type we wrote after Either (the left type) is Integer.

I don't understand number conversions in Haskell

Here is what I'm trying to do:
isPrime :: Int -> Bool
isPrime x = all (\y -> x `mod` y /= 0) [3, 5..floor(sqrt x)]
(I know I'm not checking for division by two--please ignore that.)
Here's what I get:
No instance for (Floating Int)
arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `floor', namely `(sqrt x)'
In the expression: floor (sqrt x)
In the second argument of `all', namely `[3, 5 .. floor (sqrt x)]'
I've spent literally hours trying everything I can think of to make this list using some variant of sqrt, including nonsense like
intSqrt :: Int -> Int
intSqrt x = floor (sqrt (x + 0.0))
It seems that (sqrt 500) works fine but (sqrt x) insists on x being a Floating (why?), and there is no function I can find to convert an Int to a real (why?).
I don't want a method to test primality, I want to understand how to fix this. Why is this so hard?
Unlike most other languages, Haskell distinguishes strictly between integral and floating-point types, and will not convert one to the other implicitly. See here for how to do the conversion explicitly. There's even a sqrt example :-)
The underlying reason for this is that the combination of implicit conversions and Haskel's (rather complex but very cool) class system would make type reconstruction very difficult -- probably it would stretch it beyond the point where it can be done by machines at all. The language designers felt that getting type classes for arithmetic was worth the cost of having to specify conversions explicitly.
Your issue is that, although you've tried to fix it in a variety of ways, you haven't tried to do something x, which is exactly where your problem lies. Let's look at the type of sqrt:
Prelude> :t sqrt
sqrt :: (Floating a) => a -> a
On the other hand, x is an Int, and if we ask GHCi for information about Floating, it tells us:
Prelude> :info Floating
class (Fractional a) => Floating a where
pi :: a
<...snip...>
acosh :: a -> a
-- Defined in GHC.Float
instance Floating Float -- Defined in GHC.Float
instance Floating Double -- Defined in GHC.Float
So the only types which are Floating are Floats and Doubles. We need a way to convert an Int to a Double, much as floor :: (RealFrac a, Integral b) => a -> b goes the other direction. Whenever you have a type question like this, you can ask Hoogle, a Haskell search engine which searches types. Unfortunately, if you search for Int -> Double, you get lousy results. But what if we relax what we're looking for? If we search for Integer -> Double, we find that there's a function fromInteger :: Num a => Integer -> a, which is almost exactly what you want. And if we relax our type all the way to (Integral a, Num b) => a -> b, you find that there is a function fromIntegral :: (Integral a, Num b) => a -> b.
Thus, to compute the square root of an integer, use floor . sqrt $ fromIntegral x, or use
isqrt :: Integral i => i -> i
isqrt = floor . sqrt . fromIntegral
You were thinking about the problem in the right direction for the output of sqrt; it returned a floating-point number, but you wanted an integer. In Haskell, however, there's no notion of subtyping or implicit casts, so you need to alter the input to sqrt as well.
To address some of your other concerns:
intSqrt :: Int -> Int
intSqrt x = floor (sqrt (x + 0.0))
You call this "nonsense", so it's clear you don't expect it to work, but why doesn't it? Well, the problem is that (+) has type Num a => a -> a -> a—you can only add two things of the same type. This is generally good, since it means you can't add a complex number to a 5×5 real matrix; however, since 0.0 must be an instance of Fractional, you won't be able to add it to x :: Int.
It seems that (sqrt 500) works fine…
This works because the type of 500 isn't what you expect. Let's ask our trusty companion GHCi:
Prelude> :t 500
500 :: (Num t) => t
In fact, all integer literals have this type; they can be any sort of number, which works because the Num class contains the function fromInteger :: Integer -> a. So when you wrote sqrt 500, GHC realized that 500 needed to satisfy 500 :: (Num t, Floating t) => t (and it will implicitly pick Double for numeric types like that thank to the defaulting rules). Similarly, the 0.0 above has type Fractional t => t, thanks to Fractional's fromRational :: Rational -> a function.
… but (sqrt x) insists on x being a Floating …
See above, where we look at the type of sqrt.
… and there is no function I can find to convert an Int to a real ….
Well, you have one now: fromIntegral. I don't know why you couldn't find it; apparently Hoogle gives much worse results than I was expecting, thanks to the generic type of the function.
Why is this so hard?
I hope it isn't anymore, now that you have fromIntegral.

Reliable cube root in Haskell

I am doing question 62 at project euler and came up with the following to test whether a number is cubic:
isInt x = x == fromInteger (round x)
isCube x= isInt $ x**(1/3)
But due to floating point error, it returns incorrect results:
*Main> isCube (384^3)
False
Is there a way to implement a more reliable cube test?
On a side-note, here is the rest of my solution, which doesn't work because of a type interface error on filter (isCube) (perms n):
cubes = [n^3|n<-[1..]]
perms n = map read $ permutations $ show n :: [Integer]
answer = head [n|n<-cubes,(length $ filter (isCube) (perms n)) == 5]
What do I need to do to fix the error?
No instances for (Floating Integer, RealFrac Integer)
arising from a use of `isCube' at prob62.hs:10:44-49
Any optimisations are also welcome ;-)
Try to avoid using floating point numbers as much as possible, especially when you have a problem which concerns integer values. Floating point numbers have problems with rounding and that certain values (like 1/3) cannot be represented exactly. So it's no surprise that you get mysterious answers.
First of all, in order to fix your type error you have to redefine isCube. If you check it's type signature it looks like this:
isCube :: (RealFrac a, Floating a) => a -> Bool
Note that it expects something that is of class Floating as its first argument. Your problem is that you want to use this function on integer values and integers are not an instance of Floating. You can redefine isCube like this to make the function type check.
isCube x = isInt $ (fromIntegral x) ** (1/3)
However, that will not make your program correct.
One way to make your program more correct is to do what Henrik suggested. It would look like this:
isCube x = (round (fromIntegral x ** (1/3))) ^ 3 == x
Good luck!
Don't know much about Haskell, but I would take the cube root, round to the nearerst integer, take the cube, and compare to the original value.
For another approach useful for Integer values have a look at the integerCubeRoot function in the arithmoi package.
Example:
ghci> import Math.NumberTheory.Powers.Cube
ghci> let x = 12345^3333
ghci> length $ show x
13637
ghci> isCube x
True
ghci> isCube (x+1)
False
ghci> length $ show $ integerCubeRoot x
4546
perms has the type [Integer]. isCube has the type (RealFrac a, Floating a) => a -> Bool (as you can check in GHCI). The RealFrac constraint comes from round x, the Floating constraint comes from x**(1/3). Since Integer is neither RealFrac nor Floating, isCube can't be used as Integer -> Bool. So filter isCube (perms n) doesn't make sense.
So you need to fix isCube to work properly on Integers:
isCube x = isInt $ (fromInteger x)**(1/3)
In fact, the reason isCube (384^3) even compiles is that it "really" means isCube ((fromInteger 384)^(fromInteger 3)).
Of course, this will still work badly due to floating point errors. Basically, checking floating numbers for equality, as you do in isInt, is almost always a bad idea. See other answers for explanation how to make a better test.

Resources