简体   繁体   中英

how is 'show' implemented in Haskell?

I am trying to understand how type system works in Haskell.

class (Show a) => MyShow a where 
    myShow :: a -> String

instance MyShow Integer where 
    myShow = show 

myshow :: (Show a) => a -> String
myshow = show

main  = do 
    putStrLn $ myshow 1
    putStrLn $ myShow (2 :: Integer) -- why do I need '::Integer' here?

Why does 'myshow 1' work without a type, while 'myShow 2' causes an error without an explicit type:

Ambiguous type variable `a0' in the constraints:
  (MyShow a0) arising from a use of `myShow'
              at nooverinst.hs:12:16-21
  (Num a0) arising from the literal `2' at nooverinst.hs:12:23
Probable fix: add a type signature that fixes these type variable(s)
In the second argument of `($)', namely `myShow 2'
In the expression: putStrLn $ myShow 2
In the expression:
  do { putStrLn $ myshow 1;
       putStrLn $ myShow 2 }

What's also strange is that when using GHCI there is no error:

*Main> myShow 2
"2"

So, what is the difference between 'myshow' and 'myShow' in this case? They are both defined to be the same as 'show'. What am I missing?

UPDATE:

Summary of answers: This behavior has to do with defaulting. The fact that 'show 1' and 'myshow 1' work is a special case (see Haskell report section on defaulting ). Adding 'default ()' on top of the source code turns off defaulting and results in the code breaking at 'myshow 1' because the type ambiguity isn't resolved by defaulting any more. So, in fact, both putStrLn lines should have type signatures at the end.

Thanks to everyone who answered!

This has to do with defaulting (one of the darker corners of the Haskell standard), as described at http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.4

In short, Haskell treats numeric classes in a special way, and defaults ambiguities arising on numeric classes automatically, but only if the other constraints involved are base classes. In that sense, Show is also special, and MyShow that you define yourself is treated in a different way.

And in GHCi, extended default rules kick in, which relax the restrictions slightly. These are described at http://www.haskell.org/ghc/docs/latest/html/users_guide/interactive-evaluation.html#extended-default-rules

Since 1 can have any Num type the compiler has to use some means to pick some type. This is is handled by the defaulting. But defaulting only happens for the Prelude classes and not for yours. Check out the section about defaulting in the Haskell report and it is all spelled out.

There are several numeric types (instances of Num ) and Haskell doesn't know which one you mean when you write 2 . Often you can get away with it because ghc/ghci is programmed to choose a default type like Integer for expressions like 2+2 . You're getting away with it in myshow because Haskell is using the Show instance that's tied to the Num instance that it's choosing automatically, but not in myShow .

Your own typeclass MyShow doesn't have anything to do with Num , so Haskell can't use the default rule to choose for you. [Sorry my pervious version got this the wrong way round.]

This is just a weirdness for numeric literals like 3 , 6.7 etc because they're overloaded (can represent data of more than one type), so you won't run into this problem with other types like Char etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM