I have the following function that acts like an index operator:
let {
index :: [a]->Int->Maybe a
index [] i = error "Empty list"
index l i = if i <= ((length l) - 1) && i >= 0 then
Just(l !! i)
else
error "Index out of bounds"
}
Now, initially i wrote this without using Just
(and i still don't understand what it is after googling):
let {
index :: [a]->Int->Maybe a
index [] i = error "Empty list"
index l i = if i <= ((length l) - 1) && i >= 0 then
(l !! i)
else
error "Index out of bounds"
}
To me it the above function makes perfect sense. Because here i have a function that accepts a list of 'generic type' a
and an Int
which is the index and returns Maybe
value of type a
or throws runtime exception. However, i don't understand the bit where GHCi tells me this:
<interactive>:1:120:
Couldn't match type `a' with `Maybe a'
`a' is a rigid type variable bound by
the type signature for index :: [a] -> Int -> Maybe a
at <interactive>:1:34
Expected type: [Maybe a]
Actual type: [a]
In the first argument of `(!!)', namely `l'
In the expression: (l !! i)
Now, why is GHCi getting confused with the type of l
and why is it expecting a list of type Maybe a
? Finally, how does Just
resolve the problem?
You've specifically stated in your type annotation that your function index
returns a Maybe a
.
Maybe is a data type defined in Haskell thusly:
data Maybe a = Just a | Nothing
That is, it has two value constructors, Just :: a -> Maybe a
and Nothing :: Maybe a
. Thus, in order for you function to work correctly, it must return either a Just a
or a Nothing
.
This also means that you should be able to remove your error statements with a bit of thought and encode the actual error in the Nothing
(ie. we were out of bounds, no element here!) and only return a result Just a
if it makes sense.