selectMenu :: Int->IO()
selectMenu num
|(num==2)=convertBinToDecimal
convertBinToDecimal:: IO()
convertBinToDecimal= do
putStrLn("\n\tConvert Binary To Decimal\n")
putStrLn("----------------------------------------------------------\n")
putStrLn("Enter 5 binary numbers [,,] : ")
input<-getLine
let n=(read input)::Int
--putStrLn (show n)
let result = convertionTO binaryToDec n
putStrLn(show result)
this code seems fine.but there is an error.
Any solutions to fix this error?
Thank you
You're trying to use reverse on x, which is an Int (since it's the argument of binaryToDec, which you have given the type Int -> Int), but reverse has the type [a] -> [a], so it only works on lists.
This is basically what the compiler means when it says "cannot match expected type [a] with actual type Int in the first argument of reverse". It's a good idea to read the error messages carefully, they often provide good clues to what is wrong.
To fix this, you probably want to convert x to a list somehow, or change the function to take a list instead.
Like hammar said you cannot reverse Int. You need to convert your number to list somehow with :: Int -> [Int]
Here is some kludges to do that.
listToNum :: [Int] -> Int
listToNum = foldl1 ( (+) . (*10) )
numToList :: Int -> [Int]
numToList n | n <= 9 = [n]
| otherwise = numToList (n `div` 10) ++ [n `mod` 10]
And then you can use it like reverse $ numToList x instead of reverse x.
And just a note. Your selectmenu function did not matches all possible cases. What if num is not equal to 2?
Related
So I am trying to build a program that receives a list of numbers and checks if they're integer. If the numbers are, put them in a result list.
I tried something like that but did not work (all the functions works only mylist)
numberisInteger number = number == fromInteger(round number)
one :: Float -> [Float]
one x = if numberisInteger x then [x] else []
two xs = [one x | x <- xs]
toint :: [Float] -> [Int]
toint = roundd
roundd xs = [round x | x <- xs]
mylist xs = [toint x | x <- xs]
main :: IO ()
main = return ()
A description of what the code did: numberisIntger is function that check if a number integer or not and it gives back true or false, one is function its parameter if its integer then it put it in a list if not it gives an empty one, two function is like one but as a comprehension, toint function covert a list of float to int.
Given your function (with truncate rather than round), it seems that all you need is filter:
isInteger :: RealFrac a => a -> Bool
isInteger x = fromIntegral (truncate x) == x
integers :: RealFrac a => [a] -> [a]
integers = filter isInteger
RealFrac a => a could be Float or Double. Since the rounding functions of RealFrac don't make further restrictions, neither does this function need to: a is some RealFrac and b is some Integral.
Note that if you were using Data.Ratio / Rational to express lossless fractional numbers, you'd know that something is an integer when denominator is 1.
I want to add two positive numbers together without the use of any basic operators like + for addition. I've already worked my way around that (in the add''' function) (i think) may not be efficient but thats not the point right now. I am getting lots of type errors however which i have no idea how to handle, and is very confusing for me as it works on paper and i've come from python.
add 1245 7489
--add :: Int -> Int -> Int
add x y = add'' (zip (add' x) (add' y))
where
add' :: Int -> [Int]
add' 0 = []
add' x = add' (x `div` 10) ++ [x `mod` 10]
conversion [1,2,4,5] [7,4,8,9] then zipping them together [(1,7),(2,4)....]
add'' :: [(Int,Int)] -> [Int]
add'' (x:xs) = [(add''' (head x) (last x))] ++ add'' xs
summary [8,6,...] what happens when the sum reaches 10 is not implemented yet.
where
--add''' :: (Int,Int) -> Int
add''' x y = last (take (succ y) $ iterate succ x)
adding two numbers together
You can't use head and last on tuples. ...Frankly, you should never use these functions at all because they're unsafe (partial), but they can be used on lists. In Haskell, lists are something completely different from tuples.To get at the elements of a tuple, use pattern matching.
add'' ((x,y):xs) = [add''' x y] ++ add'' xs
(To get at the elements of a list, pattern matching is very often the best too.) Alternatively, you can use fst and snd, these do on 2-tuples what you apparently thought head and last would.
Be clear which functions are curried and which aren't. The way you write add''', its type signature is actually Int -> Int -> Int. That is equivalent to (Int, Int) -> Int, but it's still not the same to the type checker.
The result of add'' is [Int], but you're trying to use this as Int in the result of add. That can't work, you need to translate from digits to numbers again.
add'' doesn't handle the empty case. That's fixed easily enough, but better than doing this recursion at all is using standard combinators. In your case, this is only supposed to work element-wise anyway, so you can simply use map – or do that right in the zipping, with zipWith. Then you also don't need to unwrap any tuples at all, because it works with a curried function.
A clean version of your attempt:
add :: Int -> Int -> Int
add x y = fromDigits 0 $ zipWith addDigits (toDigits x []) (toDigits y [])
where
fromDigits :: Int -> [Int] -> Int
fromDigits acc [] = acc
fromDigits acc (d:ds)
= acc `seq` -- strict accumulator, to avoid thunking.
fromDigits (acc*10 + d) ds
toDigits :: Int -> [Int] -> [Int] -- yield difference-list,
toDigits 0 = id -- because we're consing
toDigits x = toDigits (x`div`10) . ((x`mod`10):) -- left-associatively.
addDigits :: Int -> Int -> Int
addDigits x y = last $ take (succ x) $ iterate succ y
Note that zipWith requires both numbers to have the same number of digits (as does zip).
Also, yes, I'm using + in fromDigits, making this whole thing pretty futile. In practice you would of course use binary, then it's just a bitwise-or and the multiplication is a left shift. What you actually don't need to do here is take special care with 10-overflow, but that's just because of the cheat of using + in fromDigits.
By head and last you meant fst and snd, but you don't need them at all, the components are right there:
add'' :: [(Int, Int)] -> [Int]
add'' (pair : pairs) = [(add''' pair)] ++ add'' pairs
where
add''' :: (Int, Int) -> Int
add''' (x, y) = last (take (succ y) $ iterate succ x)
= iterate succ x !! y
= [x ..] !! y -- nice idea for an exercise!
Now the big question that remains is what to do with those big scary 10-and-over numbers. Here's a thought: produce a digit and a carry with
= ([(d, 0) | d <- [x .. 9]] ++ [(d, 1) | d <- [0 ..]]) !! y
Can you take it from here? Hint: reverse order of digits is your friend!
the official answer my professor gave
works on positive and negative numbers too, but still requires the two numbers to be the same length
add 0 y = y
add x y
| x>0 = add (pred x) (succ y)
| otherwise = add (succ x) (pred y)
The other answers cover what's gone wrong in your approach. From a theoretical perspective, though, they each have some drawbacks: they either land you at [Int] and not Int, or they use (+) in the conversion back from [Int] to Int. What's more, they use mod and div as subroutines in defining addition -- which would be okay, but then to be theoretically sound you would want to make sure that you could define mod and div themselves without using addition as a subroutine!
Since you say efficiency is no concern, I propose using the usual definition of addition that mathematicians give, namely: 0 + y = y, and (x+1) + y = (x + y)+1. Here you should read +1 as a separate operation than addition, a more primitive one: the one that just increments a number. We spell it succ in Haskell (and its "inverse" is pred). With this theoretical definition in mind, the Haskell almost writes itself:
add :: Int -> Int -> Int
add 0 y = y
add x y = succ (add (pred x) y)
So: compared to other answers, we can take an Int and return an Int, and the only subroutines we use are ones that "feel" more primitive: succ, pred, and checking whether a number is zero or nonzero. (And we land at only three short lines of code... about a third as long as the shortest proposed alternative.) Of course the price we pay is very bad performance... try add (2^32) 0!
Like the other answers, this only works for positive numbers. When you are ready for handling negative numbers, we should chat again -- there's some fascinating mathematical tricks to pull.
I would like to get all sub numbers of a number from a particular side.
In the case of the number 1234, the sub numbers from the left side are:
1, 12, 123, 1234
I implemented it with:
tail . inits $ show 1234
This way I get all the sub numbers in [[Char]] format.
["1","12","123","1234"]
I tried to convert them to Integer, with the following line.
map read . tail . inits $ show 1234
But I get the following error
[*** Exception: Prelude.read: no parse
What am I doing wrong?
because the interpreter does not know what type you want back
this will work:
λ> map read . tail . inits $ show 1234 :: [Int]
[1,12,123,1234]
of course you can just add a type-signature as well (most likely in your code file):
subnums :: Int -> [Int]
subnums = map read . tail . inits . show
in ghci:
λ> subnums 1234
[1,12,123,1234]
and a nice exercise can be to do this without show/read:
subnumbers :: Int -> [Int]
subnumbers 0 = []
subnumbers n =
n : subnumbers (n `div` 10)
Can you solve the problem with the order here?
A good approach is to use an unfold. While a fold (variously known as reduce, accumulate or aggregate in other languages) can process a list of numbers (or values of other types) to compute a single result value, an unfold starts with a single value and expands it into a list of values according to a given function. Let us examine the type of an unfold function:
Data.List.unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
We see that unfoldr take a function (b -> Maybe (a, b), and a starting b. The result is a [a]. If the function evaluates to Just (a, b), the a will be appended to the result, and the unfold recurses with the new b. If the function evaluates to Nothing, the unfold is complete.
The function for your unfold is:
f :: Integral b => b -> Maybe (b, b)
f x = if x > 0
then Just (x, x `div` 10) -- append x to result; continue with x/10
else Nothing -- x = 0; we're done
Now we can solve your problem without any of this show and read hackery:
λ> let f = (\x -> if x > 0 then Just (x, x `div` 10) else Nothing)
λ> reverse $ unfoldr f 1234
[1,12,123,1234]
As Carsten suggests, you need to give some indication of what type you want. This is because read is polymorphic in its result type. Until the compiler knows what type you want, it doesn't know what parser to use! An explicit type annotation is usually the way to go, but you might sometimes consider the function
asTypeOf :: a -> a -> a
asTypeOf x _ = x
how to use this here
I see two obvious ways to use asTypeOf here:
λ> asTypeOf (map read . tail . inits $ show 1234) ([0] :: [Int])
[1,12,123,1234]
and
λ> map (asTypeOf read length) . tail . inits $ show 1234
[1,12,123,1234]
the first one seems hardly better at all and the second might be a bit tricky for beginners - but it works ;)
Why? Because length has type [a] -> Int and so the result type will be fixed to Int:
λ> :t (`asTypeOf` length)
(`asTypeOf` length) :: ([a] -> Int) -> [a] -> Int
which is just what we need for read
Please note that it's not important what length does - only it's type is important - any other function with an compatible signature would have worked as well (although I can come up only with length right now)
For example:
wantInt :: [a] -> Int
wantInt = undefined
λ> map (asTypeOf read wantInt) . tail . inits $ show 1234
[1,12,123,1234]
A working list comprehension solution:
subNums :: Int -> [Int]
subNums num = [read x | let str = show num, let size = length str, n <- [1 .. size], let x = take n str]
λ> subNums 1234
[1,12,123,1234]
I am writing code in Haskell that acts like take, except it takes elements from the end of a list.
snatch :: (Num a, Ord a) => a -> [b] -> [b]
snatch n _
| n <= 0 = []
snatch _ [] = []
snatch n x = reverse (take n (reverse x))
The problem is with this line,
snatch n x = reverse (take n (reverse x))
It basically states that for take n, n has to be an Int. However, a is a Num type. If I change the definition of the function to this,
snatch :: Int -> [b] -> [b]
Then it works fine. I've tried reading the docs and searching the internet. But I can't find out why. Int is apparently a class of Num. So shouldn't this work? Why doesn't it work?
take, as the name suggests, takes n elements. Going by your logic, if Num was the only criteria, then your function should be able to take, say, 5.4343 elements from the list. Only, that doesn't make sense.
Therefore, in this case, even if Int is an instance of Num, the properties required are those specific to Int.
I'm trying to write a program in Haskell
that gets a list (of integer) and prints out the number of elements that are bigger than the list's average
So far I tried
getAVG::[Integer]->Double
getAVG x = (fromIntegral (sum x)) / (fromIntegral (length x))
smallerThanAVG:: [Integer]->Integer
smallerThanAVG x = (map (\y -> (if (getAVG x > y) then 1 else 0)) x)
For some reason I'm getting this error
Couldn't match expected type `Double'
against inferred type `Integer'
Expected type: [Double]
Inferred type: [Integer]
In the second argument of `map', namely `x'
It could be that I haven't written the logic correctly, although I think I did..
Ideas?
These errors are the best kind, because they pinpoint where you have made a type error.
So let's do some manual type inference. Let's consider the expression:
map (\y -> (if (getAvg x > y) then 1 else 0)) x
There are a few constraints we know off the bat:
map :: (a -> b) -> [a] -> [b] -- from definition
(>) :: Num a => a -> a -> Bool -- from definition
getAvg :: [Integer] -> Double -- from type declaration
1, 0 :: Num a => a -- that's how Haskell works
x :: [Integer] -- from type declaration of smallerThanAVG
Now let's look at the larger expressions.
expr1 = getAvg x
expr2 = (expr1 > y)
expr3 = (if expr2 then 1 else 0)
expr4 = (\y -> expr3)
expr5 = map expr4 x
Now let's work backwards. expr5 is the same as the RHS of smallerThanAVG, so that means it has the same result type as what you've declared.
expr5 :: Integer -- wrong
However, this doesn't match our other constraint: the result of map must be [b] for some b. Integer is definitely not a list (although if you get facetious, it could be coerced into a list of bits). You probably meant to sum that list up.
expr6 = sum expr5
sum :: Num a => [a] -> a
Now let's work forwards.
expr1 :: Double -- result type of getAvg
y :: Double -- (>) in expr2 requires both inputs to have the same type
expr4 :: (Integer -> [a]) -- because for `map foo xs` (expr5)
-- where xs :: [a], foo must accept input a
y :: Integer -- y must have the input type of expr4
Herein lies the conflict: y cannot be both a Double and an Integer. I could equivalently restate this as: x cannot be both a [Double] and [Integer], which is what the compiler is saying. So tl;dr, the kicker is that (>) doesn't compare different types of Nums. The meme for this sort of problem is: "needs more fromIntegral".
(getAvg x > fromIntegral y)
Your code has two errors.
Although the type signature in the code declares that smallerThanAVG x evaluates to an Integer, its code is map ... x, which clearly evaluates to a list instead of a single Integer.
In the code getAVG x > y, you are comparing a Double to an Integer. In Haskell, you can only compare two values of the same type. Therefore, you have to use fromIntegral (or fromInteger) to convert an Integer to a Double. (This is essentially what caused the error message in the question, but you have to get used to it to figure it out.)
There are several ways to fix item 1 above, and I will not write them (because doing so would take away all the fun). However, if I am not mistaken, the code you are aiming at seems like counting the number of elements that are smaller than the average, in spite of what you write before the code.
Styling tips:
You have many superfluous parentheses in your code. For example, you do not have to parenthesize the condition in an if expression in Haskell (unlike if statement in C or Java). If you want to enjoy Haskell, you should learn Haskell in a good style instead of the Haskell which just works.
You call the variable which represents a list “x” in your code. It is conventional to use a variable name such as xs to represent a list.
Others have explained the errors beautifully.
I'm still learning Haskell but I'd like to provide an alternative version of this function:
greaterThanAvg :: [Int] -> [Int]
greaterThanAvg xs = filter (>avg) xs
where avg = sum xs `div` length xs
cnt = length $ greaterThanAvg [1,2,3,4,5]