I'm learning Haskell and I've decided to to the H-99 problem set. Naturally, I've become stuck on the first problem!
I have the following code:
module Main where
getLast [] = []
getLast x = x !! ((length x) - 1)
main = do
putStrLn "Enter a list:"
x <- readLn
print (getLast x)
Compiling this code gives the following error:
h-1.hs:8:14:
No instance for (Read a0) arising from a use of `readLn'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Read () -- Defined in `GHC.Read'
instance (Read a, Read b) => Read (a, b) -- Defined in `GHC.Read'
instance (Read a, Read b, Read c) => Read (a, b, c)
-- Defined in `GHC.Read'
...plus 25 others
In a stmt of a 'do' block: x <- readLn
In the expression:
do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
In an equation for `main':
main
= do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
h-1.hs:9:9:
No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 26 others
In a stmt of a 'do' block: print (getLast x)
In the expression:
do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
In an equation for `main':
main
= do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
That's a large error, but it seems to me that Haskell isn't sure what the input type will be. That's fine, and completely understandable. However, as this is supposed to work on a list of generics, I'm not sure how to specify that type. I tried this:
x :: [a] <- readLn
...as [a] is the type that Haskell returns for an empty list (found with :t []). This won't compile either.
As I'm a beginner, I know there's a lot I'm missing, but in a basic sense - how can I satisfy Haskell's type system with input code? I'm a Haskell beginner looking for a beginner answer, if that's at all possible. (Also, note that I know there's a better way to do this problem (reverse, head) but this is the way I came up with first, and I'd like to see if I can make it work.)
You can't hope to write something like this which will detect the type of x at run time -- what kind of thing you're reading must be known at compile time. That's why @Sibi's answer uses [Int]. If it can't be deduced, you get a compile time error.
If you want a polymorphic read, you have to construct your own parser which lists the readable types.
maybeDo :: (Monad m) => Maybe a -> (a -> m b) -> m b
maybeDo f Nothing = return ()
maybeDo f (Just x) = f x
main = do
str <- getLine
maybeDo (maybeRead str :: Maybe Int) $ \i ->
putStrLn $ "Got an Int: " ++ show i
maybeDo (maybeRead str :: Maybe String) $ \s ->
putStrLn $ "Got a String: " ++ show s
There are lots of ways to factor out this repetition, but at some point you'll have to list all the types you'll accept.
(An easy way to see the problem is to define a new type MyInt which has the same Read instance as Int -- then how do we know whether read "42" should return an Int or a MyInt?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With