2

I am having problem understanding signatures/arguments/inputs of Haskell functions. Before anyone complains, yes I have done my research but can not seem to find a good answer or explanation.

basically I have a function :

update :: Eq a => (a->b) -> b -> a -> (a->b)

How do I make sense of (a->b) -> b -> a -> (a->b)? I see it as taking an input of a function followed by 2 values and outputting a function??

I have 2 different functions which do same thing, one which uses 3 arguments and one with 4 but the header (arguments of function) is same.

(1)

update :: Eq a => (a->b) -> b -> a -> (a->b)
update s v x y = if x==y then v else s y

(2)

update :: Eq a => (a->b) -> b -> a -> (a->b)
update s v y = ss
  where ss x = if ( x == y )
                 then v
                 else s x

They both compute same thing but I do not understand why (1) uses 4 inputs "update s v x y" and (2) "update s v y" uses 3 inputs.

Any help will be greatly appreciated.

2
  • Did you not come across currying in your research? (1) is a function with 4 arguments returning a value of type b. (2) is a functions with 3 arguments returning a function with 1 argument returning a value of type b. But actually Haskell only has functions with one argument. So both (1) and (2) are functions returning a function returning a function returning a function returning a value of type b (which might be a function, of course). Commented Apr 11, 2014 at 14:27
  • I'd say that your update (1) is (a -> b) -> b -> a -> a -> b, so it's visibly a function of 4 arguments; ghci's :t also says so. Removing the parens around the last a -> b is just currying. Commented Apr 11, 2014 at 14:30

1 Answer 1

6

Welcome to the wonderful world of currying.

Let's start with a simple function

allEq :: Int -> Int -> Int -> Bool
allEq x y z = x == y && y == z

Now in Haskell -> is right associative, so this is

allEq :: Int -> (Int -> (Int -> Bool)))
allEq x y z = x == y && y == z

allEq x y = \z -> x == y && y == z
allEq x = \y -> \z -> x == y && y == z
allEq = \x -> \y -> \z -> x == y && y == z

Now, in Haskell we know that we can "lift" an expression into a let or where binding without changing it.

 allEq x y = foo
   where foo z = x == y && y == z

And this is how we get to your function.

Sign up to request clarification or add additional context in comments.

4 Comments

Great answer, thank you. Just one thing, when I do this outside a function and in console, let allEq x = \y -> \z -> x == y && y == z, it works as it should but let alleq = \x -> \y -> \z -> x == y && y == z gives an error, why is this?
@user2371066 That's entirely unrelated to something called "the monomorphism restriction".
one last thing if you are free, as I asked above, I think (a->b) -> b -> a -> (a->b) is taking in a function and 2 values and outputting a function, then why do we have 4 values "update s v x y"? how do I read this correctly?
@user2371066 Remember that since it's right assocative it's just (a -> b) -> b -> a -> a -> b

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.