Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare function (type misunderstanding Maybe)

Tags:

haskell

I need a function which works like:

some :: (Int, Maybe Int) -> Int
some a b
     | b == Nothing = 0
     | otherwise = a + b

Use cases:

some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]

But my code raise the error:

The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one

I don't understand it.

Thanks in advance.

like image 510
ceth Avatar asked Apr 10 '26 02:04

ceth


2 Answers

When you write

foo x y = ...

That is notation for a curried function, with a type like:

foo :: a -> b -> c

You have declared your function to expect a tuple, so you must write it:

some :: (Int, Maybe Int) -> Int
some (x, y) = ...

But Haskell convention is usually to take arguments in the former curried form. Seeing funcitons take tuples as arguments is very rare.

For the other part of your question, you probably want to express it with pattern matching. You could say:

foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1

Generalizing that to the OP's question is left as an exercise for the reader.

like image 99
luqui Avatar answered Apr 12 '26 16:04

luqui


Your error doesn't come from a misunderstanding of Maybe: The type signature of some indicates that it takes a pair (Int, Maybe Int), while in your definition you provide it two arguments. The definition should thus begin with some (a,b) to match the type signature.

One way to fix the problem (which is also a bit more idiomatic and uses pattern matching) is:

some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b

It's also worth noting that unless you have a really good reason for using a tuple as input, you should probably not do so. If your signature were instead some :: Int -> Maybe Int -> Int, you'd have a function of two arguments, which can be curried. Then you'd write something like

some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b

Also, you might want to add the following immediate generalization: All Num types are additive, so you might aswell do

some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b

(I've violated the common practice of using a, b, c... for type variables so as not to confuse the OP since he binds a and b to the arguments of some).

like image 31
gspr Avatar answered Apr 12 '26 16:04

gspr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!