Here is a working version of your code:
oddsort :: Int -> [Int] -> [Int]
oddsort x xs
|x == 1 = x : xs
|x `mod` 2 == 0 = oddsort (x - 1) (x:xs)
|otherwise = oddsort (x - 2) (x:xs)
main = do
putStrLn "This program can find all odd numbers between 1 and a desired number. Please enter a number."
user <- getLine
if (read user :: Int) < 1
then putStrLn $ "Improper input specified. 10 will be chosen as default. \n" ++ ((show $ oddsort 10 []) ++ " Is the list of odd numbers from 1 to 10.")
else putStrLn $ show $ (oddsort (read user :: Int) [])
I made a few changes to your code and listed them in order.
The first thing I did was add a type signature to oddsort
because otherwise the type signature is left to the compiler to inference (guess) the type and you don't really want to do that with functions, why? well check this.
Then I changed if (read user) < 1
to if (read user :: Int) < 1
, because again you're leaving it up to the compiler to guess the return of read
and read returns a specific type once you've defined the signature for the return type :: Int
which specifies that the return type of read
is an Int
.
The last change was in then
clause, I simply removed your second putStrLn
statement and concatenated the result of (show $ oddsort 10 [])
to "Is the list of odd numbers from 1 to 10.")
because by having putStrLn show oddsort 10 []
GHC will take everything after show as an argument and putStrLn can only take strings and only 1 argument at that. You can see this on the repl by typing :t show
. Also I concatenated them to 1 string because you really only need 1 but 2 looks neater so keep it that way but add parenthesis to your second putStrLn so there is only 1 argument. You can also use $
operator for this.