peeyush singh
peeyush singh

Reputation: 1407

Does haskell hide types if the same name is used in a different module?

EDIT

All thee answers did explain it well enough, just one final thing, can anyone point me to the documentation about the types, so I can understand how the types are handled internally

I am trying to implement a wrapper type for IO, to understand types. I have created a IO' type which is actually using the IO to construct.

data IO' a = IO a

test :: String -> IO' String
test x = IO x 

convert :: IO' String -> String
convert (IO x) =  x

main = do
        a <- getLine
        return $ convert.test $ a

However now if I try to use IO to return an IO action then it fails, example the following function fails giving the expected vs actual type error:

fail :: IO String
fail = IO "test"

So in Haskell are types using same names get hidden? Also how do I understand whether I am using data constructor or type constructor when I call IO.

Finally, seems like a silly question but I tried to find the documentation for System.IO and later for List type as well, and am not able to find it.

Upvotes: 0

Views: 334

Answers (3)

sepp2k
sepp2k

Reputation: 370357

You're defining two things: A type named IO' and a constructor named IO. Neither of them hide anything because the standard library defines neither a type named IO' (only IO) nor a constructor named IO (the standard IO type doesn't have any constructors). So since constructors and types live in different name spaces (meaning you can have a constructor and a type with the same name without any problems), nothing is being hidden.

So with your definitions, you now have the types IO (referring to Prelude.IO) and IO' (referring to your type) and the constructor IO :: a -> IO' a.

Your definition of fail does not work because IO constructs a value of type IO', not IO. There is no connection between your IO constructor and the IO type, so there is no reason this should work.

Upvotes: 3

leftaroundabout
leftaroundabout

Reputation: 120731

Nothing is hidden in your code.

In Haskell, the type- and value-languages are strictly separated. Broadly speaking, everything to the right of a :: or data/newtype/type keyword (except the name-declaration for value constructors) lives in the type-level language, everything else lives in the value-level language.

     ┌─────┐   ┌──┐        ┌─┐
data │IO' a│ = │IO│        │a│
     └─────┤   └value-level└┬┘
           └─type-level─────┘

        ┌───────────┐
fail :: │ IO String │
        └──────────type-level
┌────────────────┐
fail = IO "test" │
└───────────────value-level

The type-level IO is unambiguously Prelude.IO (because you named your type IO' instead), whereas the value-level IO is unambiguously the data constructor to IO' that you defined yourself (because Prelude.IO does not export any constructors called either IO or otherwise).

Hiding would only become relevant if you actually used the same name IO again for the type constructor:

import Prelude hiding (IO)

data IO a = IO a

test :: String -> IO String
test x = IO x 

convert :: IO String -> String
convert (IO x) =  x

fail' :: IO String
fail' = IO "test"

Upvotes: 4

I am trying to implement a wrapper type for IO,

You did not though. There's no reference to the IO type anywhere in your data declaration.

data IO' a = IO a

That IO on the right-hand side is not the type IO. It's not even a type. That is just the name you chose for the value constructor of your data type IO'.

If you ask ghc the type of IO you'll get,

> :t IO
IO :: a -> IO' a

You could have chosen any other name for it, e.g.

data IO' a = C a

It's just a constructor for values of type IO'

Upvotes: 4

Related Questions