What is Just in Haskell and why would not this function work without her?

advertisements

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.