Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the type of local variables that are values affect the type of input variables in the type signature of a function?

Tags:

haskell

Prelude> func f = [(show s, f == s) | s <- [0, 1..10]]
Prelude> :type func
func :: (Num a, Enum a, Show a, Eq a) => a -> [(String, Bool)]

I would expect f to just be an instance of Eq a but all the class constraints applied to s are also applied to f for some reason. Replacing s with any constant removes the relevant type constraint for f, and replacing s in the equality removes all class constraints except Eq a for f.

Can someone explain to me why does the type of local variables that are values affect the type of input variables that are values?

like image 613
Anon Avatar asked Jul 27 '21 01:07

Anon


People also ask

What is the purpose of variable types?

Their sole purpose is to label and store data in memory.

What is the advantage of local variable?

Advantages of using local variables: We do not have to take care of deleting unnecessary variables when the task is complete because local variables are deleted from memory automatically when their task is complete. When you use local variables, you do not have to worry that they will be changed by another task.

Can a function change the value of a global variable?

Functions can access global variables and modify them. Modifying global variables in a function is considered poor programming practice. It is better to send a variable in as a parameter (or have it be returned in the 'return' statement).

Which type is used to store the arguments when the number of arguments for a function is not constant in C?

Variable length argument is a feature that allows a function to receive any number of arguments.


Video Answer


1 Answers

Eq doesn't exist in a vacuum. To compare two things for equality, you have to have two things. And, crucially, those two things have to be of the same type. In Haskell, 0 == "A" isn't just false; it's a type error. It literally doesn't make sense.

f == s

When the compiler sees this, even if it knows nothing else about the types of f and s, it knows what (==) is. (==) is a function with the following signature.

(==) :: Eq a => a -> a -> Bool

Both arguments are of the same type. So now and forevermore, for the rest of type-checking this expression, we must have f and s of the same type. Anything required of s is also required of f. And s takes values from [0, 1..10]. Your type constraints come as follows

  • Num is required since s takes values from a list of literal integers.
  • Enum is required by the [..] list enumeration syntax.
  • Show is required by show s.
  • Eq is required by the f == s equality expression.

Now, if we replace s with a constant, we get something like

func f = [(show s, f == 0) | s <- [0, 1..10]]

Now f is being compared with 0. It has no relation to s. f requires Eq (for (==)) and Num (since we're comparing against zero, a number). s, on the other hand, requires Enum, Num, Eq, and Show. In the abstract, this should actually be a type error, since we've given no indication as to which type s should be and there aren't enough clues to figure it out. But type defaulting kicks in and we'll get Integer out of it.

like image 128
Silvio Mayolo Avatar answered Oct 25 '22 00:10

Silvio Mayolo