Read list of unknown type from user input Haskell: - haskell

Say I have the following function:
readList :: IO [Int]
readList = do
putStrLn "Please enter the list as a string"
putStrLn "Example: input of '1 2 3 4 5' will map to [1,2,3,4,5]"
line <- getLine
return $ map read $ words line
printNaive :: [Int] -> IO ()
printNaive xs = putStrLn "The maximum surpasser count is:" >> putStrLn "0"
main :: IO ()
main = readList >>= printNaive
This function works as expected. Now lets say I was going to extend this code to be more generic, and read in a line of any type of thing as a list:
readList :: (Read a, Int a) -> IO [a]
readList = do
putStrLn "Please enter the list as a string"
putStrLn "Example: input of '1 2 3 4 5' will map to [1,2,3,4,5]"
line <- getLine
return $ map read $ words line
printNaive :: (Eq a) => [a] -> IO ()
printNaive xs = putStrLn "The maximum surpasser count is:" >> putStrLn "0"
main :: IO ()
main = readList >>= printNaive
This fails with:
Ambiguous type variable ‘a0’ arising from a use of ‘Lib.readList’
prevents the constraint ‘(Read a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Read Ordering -- Defined in ‘GHC.Read’
instance Read Integer -- Defined in ‘GHC.Read’
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
...plus 22 others
...plus four instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
How would I go about writing this code, given I really don't care what type of thing it is as long as it conforms to Eq.
Additionally, say I wanted to provide a facility to specify what type the list is going to contain. (through another getLine say).
How would I extract a type from getLine, and how would I then cast every element in the map read $ words line to that particular type.

What you did wrong is in this line:
readList :: (Read a, Int a) -> IO [a]
What you probably want to get at with (Read a, Int a) is a type class constranit for the type a, meaning you want it to be readable and you want it to be some sort of integer.
Firstly you wrote your constraint wrong. A typeclass constraint is given before a => not a ->. Secondly Int is not a type class. Maybe try using Integral?
So your type signature should look like this:
readList :: (Read a, Integral a) => IO [a]
EDIT: A caveat is, however, that the a in the type signature has to be decided at compile time. In the first example in your question it would work out because the type of printNaive fixes a to be Int. That is not generally the case, however.

Related

Getting Result of IO Monad in ghci

Given:
Prelude> let x = return 100 :: IO Int
Trying to evaluate x returns its wrapped value.
Prelude> x
100
But, I can't get its value via show.
Prelude> show x
<interactive>:4:1:
No instance for (Show (IO Int)) arising from a use of ‘show’
In the expression: show x
In an equation for ‘it’: it = show x
What's going on when I type x in ghci?
If you enter an expression of type IO t into GHCi, it unwraps it and prints the resulting value. That is if you enter ioExp, GHCi executes val <- ioExp; print val (whereas if you enter a non-IO expression exp, GHCi executes print exp).
You can't show an IO Int action. The action may require to perform side effects to produce the Int, such as asking the user for such number. Instead, the type of show promises to return a String, i.e. a plain, pure string without any side effect.
You can define your own effectful variant of show, if you want:
showIO :: Show a => IO a -> IO String
showIO = fmap show
Note how the result above is not a plain string, but is wrapped inside the IO monad, as it should be.

Specify list type for input

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?)
This should work:
getLast :: Num a => [a] -> a
getLast [] = 0
getLast x = x !! ((length x) - 1)
main = do
putStrLn "Enter a list:"
x <- readLn :: IO [Int]
print (getLast x)
why return 0 for an empty list, instead of an empty list?
Because it won't typecheck. Because you are returning [] for empty list and for other cases you are returning the element inside the list i.e a. Now since a type is not equal to list, it won't typecheck. A better design would be to catch this type of situation using the Maybe datatype.
Also, because of returning 0, the above function will work only for List of types which have Num instances created for them. You can alleviate that problem using error function.
However, this should work for a generic list, not just a list of Ints
or Numbers, right?
Yes, it should work for a polymorphic list. And you can create a function like getLast which will work for all type of List. But when you want to get input from the user, it should know what type of input you are giving. Because the typechecker won't be able to know whether you meant it as List of Int or List of Double or so on.

Can't properly define transformation from universal type, that defined with GADT

I've defined an universal data type that can contain anything (well, with current implementation not totally anything)!
Here it is (complete code):
{-#LANGUAGE NoMonomorphismRestriction#-}
{-#LANGUAGE GADTs#-}
{-#LANGUAGE StandaloneDeriving#-}
data AnyT where
Any :: (Show a, Read a) => a -> AnyT
readAnyT :: (Read a, Show a) => (String -> a) -> String -> AnyT
readAnyT readFun str = Any $ readFun str
showAnyT :: AnyT -> String
showAnyT (Any thing) = show thing
deriving instance Show AnyT --Just for convinience!
a = [Any "Hahaha", Any 123]
And I can play with it in console:
*Main> a
[Any "Hahaha",Any 123]
it :: [AnyT]
*Main> readAnyT (read::String->Float) "134"
Any 134.0
it :: AnyT
*Main> showAnyT $ Any 125
"125"
it :: String
Well, I have it, but I need to process it somehow. For example, let's define transformation functions (functions definition, add to previous code):
toAnyT :: (Show a, Read a) => a -> AnyT -- Rather useless
toAnyT a = Any a
fromAny :: AnyT -> a
fromAny (Any thing) = thing
And there is the problem! the fromAny definition from previous code is incorrect! And I don't know how to make it correct. I get the error in GHCi:
2.hs:18:23:
Could not deduce (a ~ a1)
from the context (Show a1, Read a1)
bound by a pattern with constructor
Any :: forall a. (Show a, Read a) => a -> AnyT,
in an equation for `fromAny'
at 2.hs:18:10-18
`a' is a rigid type variable bound by
the type signature for fromAny :: AnyT -> a at 2.hs:17:12
`a1' is a rigid type variable bound by
a pattern with constructor
Any :: forall a. (Show a, Read a) => a -> AnyT,
in an equation for `fromAny'
at 2.hs:18:10
In the expression: thing
In an equation for `fromAny': fromAny (Any thing) = thing
Failed, modules loaded: none.
I tried some other ways that giving errors too.
I have rather bad solution for this: defining necessary functions via showAnyT and read (replace previous function definitions):
toAnyT :: (Show a, Read a) => a -> AnyT -- Rather useless
toAnyT a = Any a
fromAny :: Read a => AnyT -> a
fromAny thing = read (showAnyT thing)
Yes, it's work. I can play with it:
*Main> fromAny $ Any 1352 ::Float
1352.0
it :: Float
*Main> fromAny $ Any 1352 ::Int
1352
it :: Int
*Main> fromAny $ Any "Haha" ::String
"Haha"
it :: String
But I think it's bad, because it uses string to transform.
Could you please help me to find neat and good solution?
First a disclaimer: I don't know the whole context of the problem you are trying to solve, but the first impression I get is that this kind of use of existentials is the wrong tool for the job and you might be trying to implement some code pattern that is common in object-oriented languaged but a poor fit for Haskell.
That said, existential types like the one you have here are usually like black holes where once you put something in, the type information is lost forever and you can't cast the value back to its original type. However, you can operate on existential values via typeclasses (as you've done with Show and Read) so you can use the typeclass Typeable to retain the original type information:
import Data.Typeable
data AnyT where
Any :: (Show a, Read a, Typeable a) => a -> AnyT
Now you can implement all the functions you have, as long as you add the new constraint to them as well:
readAnyT :: (Read a, Show a, Typeable a) => (String -> a) -> String -> AnyT
readAnyT readFun str = Any $ readFun str
showAnyT :: AnyT -> String
showAnyT (Any thing) = show thing
toAnyT :: (Show a, Read a, Typeable a) => a -> AnyT -- Rather useless
toAnyT a = Any a
fromAny can be implemented as returning a Maybe a (since you cannot be sure if the value you are getting out is of the type you are expecting).
fromAny :: Typeable a => AnyT -> Maybe a
fromAny (Any thing) = cast thing
You're using GADTs to create an existential data type. The type a in the constructor existed, but there's no way to recover it. The only information available to you is that it has Show and Read instances. The exact type is forgotten, because that's what your constructor's type instructs the type system to do. "Make sure this type has the proper instances, then forget what it is."
There is one function you've missed, by the way:
readLike :: String -> AnyT -> AnyT
readLike s (Any a) = Any $ read s `asTypeOf` a
Within the context of the pattern match, the compiler knows that whatever type a has, there is a Read instance, and it can apply that instance. Even though it's not sure what type a is. But all it can do with it is either show it, or read strings as the same type as it.
What you have is something called Existential type. If you follow that link than you will find that in this pattern the only way to work with the "data" inside the container type is to use type classes.
In your current example you mentioned that a should have Read and Show instances and that means only the functions in these type classes can be used on a and nothing else and if you want to support some more operations on a then it should be constrained with the required type class.
Think it like this: You can put anything in a box. Now when you extract something out of that box you have no way to specify what you will get out of it as you can put anything inside it. Now if you say that you can put any eatable inside this box, then you are sure that when you pick something from this box it will be eatable.

No instance for Num String arising from the literal `1'

main = do
putStrLn $myLast [1,2,3,4]
myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs
When i try to run this code i get this message:
"No instance for (Num String) arising from the literal `1'
Possible fix: add an instance declaration for (Num String)"
It runs well when I run with the list ["1","2","3,"4"]. I didn't specify the type but it doesn't work with ints.
"No instance for..." error messages are usually misleading.
The problem you have is simply this
Prelude> :t putStrLn
putStrLn :: String -> IO ()
i.e. that function can only deal with strings, not with numbers. An often-seen solution is to first translate the thing you want to show into a string: putStrLn (show x), but actually the combination exists as a much nicer standard function:
main = do
print $ myLast [1,2,3,4]
The compiler concludes from
putStrLn x
that x must be a String. The inferred type for
myLast [1,2,3,4]
is Num a => a and when you now substitute a with String you get
Num String => String
This is all quite logical, except that the type checker remembers that the Num constraint originated from the literal 1.
The message you get is thus just another way to say that a number is not a string, and putStrLn badly wants a string. Or, if you want, that the expression would be well typed, if only strings were numbers.
putStrLn has type String -> IO () so you need to convert your list element into a string first.
You can do this with show:
putStrLn $ show $ myLast [1,2,3,4]

Can Either be used for a kind of simple polymorphism?

I tried writing a simple function that takes an Either type (possibly parameterized by two different types) and does one thing if it gets Left and another thing if it gets Right. the following code,
someFunc :: (Show a, Show b) => Either a b -> IO ()
someFunc (Left x) = print $ "Left " ++ show x
someFunc (Right x) = print $ "Right " ++ show x
main = do
someFunc (Left "Test1")
someFunc (Right "Test2")
However, this gives,
Ambiguous type variable `b0' in the constraint:
(Show b0) arising from a use of `someFunc'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' expression: someFunc (Left "Test1")
and
Ambiguous type variable `a0' in the constraint:
(Show a0) arising from a use of `someFunc'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: someFunc (Right "Test2")
If I understand correctly, when I call the function with Left x, it is complaining because it doesn't know the type of the Right x variant, and vice-versa. However, this branch of the function is not used. Is there a better way to do this?
You can make this work by explicitly specifying the other type:
main = do
someFunc (Left "Test1" :: Either String ())
someFunc (Right "Test2" :: Either () String)
but I agree with x13n that this probably isn't the best way to do whatever you're trying to do. Note that someFunc is functionally identical to
someFunc :: (Show a) => Bool -> a -> IO ()
someFunc False x = print $ "Left " ++ show x
someFunc True x = print $ "Right " ++ show x
because the only information you derive from the structure of the Either is whether it's a Left or Right. This version also doesn't require you to specify a placeholder type when you use it.
This is a good question, because it made me think about why Haskell behaves this way.
class PseudoArbitrary a where
arb :: a
instance PseudoArbitrary Int where
arb = 4
instance PseudoArbitrary Char where
arb = 'd'
instance PseudoArbitrary Bool where
arb = True
reallyDumbFunc :: (PseudoArbitrary a, PseudoArbitrary b) =>
Either a b -> Either a b
reallyDumbFunc (Left x) = Right arb
reallyDumbFunc (Right x) = Left arb
So check this out. I've made a typeclass PseudoArbitrary, where instances of the typeclass provide a (pseudo-)arbitrary element of their type. Now I have a reallyDumbFunction that takes an Either a b, where both a and b have PseudoArbitrary instances, and if a Left was put in, I produce a Right, with a (pseudo-)arbitrary value of type b in it, and vice versa. So now let's play in ghci:
ghci> reallyDumbFunc (Left 'z')
Ambiguous type variable blah blah blah
ghci> reallyDumbFunc (Left 'z' :: Either Char Char)
Right 'd'
ghci> reallyDumbFunc (Left 'z' :: Either Char Int)
Right 4
Whoa! Even though all I changed was the type of the input, it totally changed the type and value of the output! This is why Haskell cannot resolve the ambiguity by itself: because that would require analyzing your function in complicated ways to make sure you are not doing things like reallyDumbFunc.
Well, that depends heavily on what you are trying to do, doesn't it? As you already found out, in order to use Left constructor, you need to know the type it constructs. And full type requires information on both a and b.
Better way to achieve polymorphism in Haskell is to use type classes. You can easily provide different implementations of "methods" for different instances.
Good comparison of both object-orientation and type classes concepts can be found here.

Resources