0
votes

I have a function

mySucc :: (Enum a, Bounded a, Eq a, Show a) => a -> Maybe a
mySucc int 
     | int == maxBound = Nothing
     | otherwise = Just $ succ int

When I want to print the output of this function in ghci, Haskell seems to be confused as to which instance of Show to use. Why is that? Shouldn't Haskell automatically resolve a's type during runtime and use it's Show?

My limited understanding of type class is that, if you mention a type (in my case a) and say that it belongs to a type class (Show), Haskell should automatically resolve the type. Isn't that how it resolves Bounded, Enum and Eq? Please correct me if my understanding is wrong.

2
How are you calling this function in GHCi?chi
Hi, it is by using "stack ghci"Srinivas

2 Answers

4
votes

Shouldn't Haskell automatically resolve a's type during runtime and use it's Show?

Generally speaking, types don't exist at runtime. The compiler typechecks your code, resolves any polymorphism, and then erases the types. But, this is kind of orthogonal to your main question.

My limited understanding of type class is that, if you mention a type (in my case a) and say that it belongs to a type class (Show), Haskell should automatically resolve the type

No. The compiler will automatically resolve the instance. What that means is, you don't need to explicitly pass a showing-method into your function. For example, instead of the function

showTwice :: Show a => a -> String
showTwice x = show x ++ show x

you could have a function that doesn't use any typeclass

showTwice' :: (a -> String) -> a -> String
showTwice' show' x = show' x ++ show' x

which can be used much the same way as showTwice if you give it the standard show as the first argument. But that argument would need to be manually passed around at each call site. That's what you can avoid by using the type class instead, but this still requires the type to be known first.

(Your mySucc doesn't actually use show in any way at all, so you might as well omit the Show a constraint completely.)

When your call to mySucc appears in a larger expression, chances are the type will in fact also be inferred automatically. For example, mySucc (length "bla") will use a ~ Int, because the result of length is fixed to Int; or mySucc 'y' will use a ~ Char. However, if all the subexpressions are polymorphic (and in Haskell, even number literals are polymorphic), then the compiler won't have any indication what type you actually want. In that case you can always specify it explicitly, either in the argument

> mySucc (3 :: Int)
Just 4

or in the result

> mySucc 255 :: Maybe Word8
Nothing
2
votes

Are you writing mySucc 1? In this case, you get a error because 1 literal is a polymorphic value of type Num a => a.

Try calling mySucc 1 :: Maybe Int and it will work.