Reputation: 97
I'm practicing some Haskell to understand the \
, case.. of
and Maybe
better.
I've got this little function here which should return Nothing
if the array is empty, Just y
if y is equal to the head of the array xs and Just (tail xs)
if y is not equal to the head of the array xs.
I set the return type of the function to Maybe a
because in one case it should return an Int
and in the other an [Int]
.
funct :: Int -> [Int] -> Maybe a
funct = \y xs -> case xs of
[] -> Nothing
xs -> if ((head xs) == y)
then Just y
else Just (tail xs)
What am I missing? I am getting the error that it couldn't match type a
with [Int]
. Isn't the a
in Maybe a
generic or is it influenced by the fact that I "used" the a
as an Int
in the Just y
part?
EDIT: Ok my suggestion was bs, I tested it with Just (tail xs)
in the then and else part and I'm still getting the same error.
Upvotes: 1
Views: 92
Reputation: 477607
set the return type of the function to
Maybe a
because in one case it should return anInt
and in the other an[Int]
.
Haskell is statically typed. Meaning it can not - at runtime - have a different return type. It can only have one return type. a
is not an ad hoc type (in the sense that it can be any type at runtime). It means that a
will be determined - at compile time - based on the types of other parameters.
For instance you can write: foo :: a -> a -> a
to specify that if foo
takes two Int
s (again known at compile time), the result will be an Int
.
You can however use Either a b
to say that you will either return a Left a
, or a Right b
. So you can rewrite it to:
funct :: Int -> [Int] -> Maybe (Either Int [Int])
funct = \y xs -> case xs of
[] -> Nothing
xs -> if ((head xs) == y)
then Just (Left y)
else Just (Right (tail xs))
Your function however is quite verbose, you can make it more clear and compact as follows:
funct :: Int -> [Int] -> Maybe (Either Int [Int])
funct _ [] = Nothing
funct y (h:t) | h == y = Just (Left y)
| otherwise = Just (Right t)
Furthermore we can generalize it to:
funct :: Eq a => a -> [a] -> Maybe (Either a [a])
funct _ [] = Nothing
funct y (h:t) | h == y = Just (Left y)
| otherwise = Just (Right t)
Here Eq
is a typeclass that specifies that there exists a function (==) :: a -> a -> Bool
that we can use. Otherwise using ==
in the body of the function would not be possible.
Furthermore we use patterns in the head of every clause. []
is a pattern that describes the empty list. (h:t)
on the other hand is a pattern describing a list containing at least one element: the head h
, followed by a (possibly empty tail t
).
Upvotes: 6