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