1
votes

p.s: I wasn't sure how to name my question, fell free to let me know how I should have named it.

If not specifying the concrete type, I get this error, which is very clear and easy to solve:

Ambiguous type variable a0 arising from a use of fct prevents the constraint (Read a0) from being solved. Probable fix: use a type annotation to specify what a0 should be.

I just need more explanation on why it worked? How Read will know what is the type to return:

fct :: (Show a, Read b) => a -> b
fct = read . show

main = do
  -- DOES NOT WORK: -- print (fct 4)   
  -- WORKS: -- print (fct 4 :: Int)
1
What is fct doing here?Willem Van Onsem
That looks like it annotating the return, not the argument. It already knows what the argument type is since you're passing a literal. You're telling it that the call to that function will evaluate to an Int, so that means that read must return an Int.Carcigenicate

1 Answers

6
votes

(fct 4 :: Int) means (fct 4) :: Int, not fct (4 :: Int). The former specifies that the result of fct must be Int, hence read must be used to turn a string into an Int.

Instead, the literal 4 is left unconstrained. This triggers the so-called defaulting rules, which choose Integer for its type. Such defaulting, roughly, happens when a numeric literal is left ambiguous. Defaulting was introduced to let code like print 4 work without annotations -- a small "special case" for programmers' convenience.

Concluding: show is called to turn 4 :: Integer into the string "4", which is then read back into 4 :: Int.