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.
You told GHC the return type of index as Maybe a. That means that (l !! i) (a value returned by index) must be of type Maybe a.
Since (l !! i) is selecting a single element out of the list l, that means l must be of type [Maybe a] in order for one of its elements to be Maybe a.
But l is the first argument to index, which you have also told GHC is typed [a].
That's exactly your error. GHC is trying to compile an index into a [Maybe a] to get a Maybe a, but instead it's found the thing being indexed is a [a].
The reason Just fixes this, is that Just is of type a -> Maybe a. So when you say Just (l !! i), GHC now sees you indexing a [a] to get an a, and then applying Just to that which results in a Maybe a, as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With