Reputation: 161
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
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
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