user3749167
user3749167

Reputation: 161

Invisible type signature in Haskell

I want to use ambiguous type a in function as follows, but it fails.

foo :: (Read a, Show a) => IO ()
foo = print =<< (readLn :: IO a)

The purpose is to get different outputs regarding to the given type signature when actually called.

>>> foo :: Double => IO ()
34   -- user input
34.0 -- output

>>> foo :: Int => IO ()
34   -- user input
34   -- output

How can I manage this?

Upvotes: 2

Views: 142

Answers (2)

Daniel Wagner
Daniel Wagner

Reputation: 152707

The simplest way is to manifest your type variable. For example, using a newish GHC:

{-# LANGUAGE ScopedTypeVariables #-}
foo :: forall proxy a. (Read a, Show a) => proxy a -> IO ()
foo _ = print (read "34" :: a)

Then, in ghci:

Data.Proxy *Main> foo (Proxy :: Proxy Double)
34.0
Data.Proxy *Main> foo (Proxy :: Proxy Int)
34

Or, a more exotic usage, relying on more implicit Haskell behavior:

*Main> foo [0.0]
34.0
*Main> foo [0]
34

Upvotes: 9

Zeta
Zeta

Reputation: 105876

Neither foo :: Double => IO () nor foo :: Int => IO () are valid signatures, since Double and Int aren't constraints.

However, you could easily make the function polymorphic in its return type and write it the following way:

foo :: (Read a, Show a) => IO a
foo = let x = read "34" in print x >> return x

That way, you can use foo :: IO Double or foo :: IO Integer:

ghci> foo :: IO Double
34.0 -- print
34.0 -- result, you would discard it
ghci> foo :: IO Integer
34
34

Upvotes: 4

Related Questions