Here's a homework problem I came across:
Input an integer, greater than or equal to 0. Multiply it by 5, add 6 to the product, multiply by 4, add 9 and multiply by 5. Then, remove the last two digits of the final number and subtract 1. Output the answer.
Here's my code:
1 main = do
2 putStrLn "enter a non-negative integer: "
3 input <- getLine
4 let i = (read input :: Int)
5 print ((((i * 5) + 6) * 4 + 9) * 5)/100-1
Here, I'm trying to truncate the last two digits by dividing it by 100, since this works in other languages.
However, it gives me this error and I'm not sure what it means:
$ runhaskell Computations.hs
Computations.hs:5:5: error:
• No instance for (Fractional (IO ())) arising from a use of ‘/’
• In the first argument of ‘(-)’, namely
‘print ((((x * 5) + 6) * 4 + 9) * 5) / 100’
In a stmt of a 'do' block:
print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1
In the expression:
do { putStrLn "enter a non-negative integer: ";
input1 <- getLine;
let x = (read input1 :: Int);
print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1 }
Computations.hs:5:5: error:
• No instance for (Num (IO ())) arising from a use of ‘-’
• In a stmt of a 'do' block:
print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1
In the expression:
do { putStrLn "enter a non-negative integer: ";
input1 <- getLine;
let x = (read input1 :: Int);
print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1 }
In an equation for ‘main’:
main
= do { putStrLn "enter a non-negative integer: ";
input1 <- getLine;
let x = ...;
.... }
So, can anyone explain what the error means?
Are there any other solutions better than trucating by a divisor?
How can I remove digits at arbitrary positions? For example, remove the first, second and sixth digits from an integer?
ps: input and output should match if done correctly.
Update: I've changed "/" to "div" and it gives me this:
Computations.hs:5:12: error:
• Couldn't match expected type ‘(Integer -> Integer -> Integer)
-> Integer -> Integer’
with actual type ‘Int’
• The function ‘(((i * 5) + 6) * 4 + 9) * 5’
is applied to two arguments,
but its type ‘Int’ has none
In the first argument of ‘(-)’, namely
‘((((i * 5) + 6) * 4 + 9) * 5) div 100’
In the first argument of ‘print’, namely
‘(((((i * 5) + 6) * 4 + 9) * 5) div 100 - 1)’
This part is strange: "The function ‘(((i * 5) + 6) * 4 + 9) * 5’ is applied to two arguments", why does haskell interpret it as a function?
Can anyone explain what the error means?
The precedence in your first line is off - infix functions (like /) usually have a higher precedence than normal ones, so print (...) / 100 is equivalent to (print ...) / 100, which is obviously problematic. You can wrap everything in brackets, or use the $ function:
print $ ((((i * 5) + 6) * 4 + 9) * 5) / 100 - 1
Now as you've constrained i to be an Int, this will still give an error: / is only defined for instances of the Fractional typeclass, and Int isn't. You want integer division, div or quot, which operates only on Integrals (of which Int is an instance) and perform truncation as you want:
print $ ((((i * 5) + 6) * 4 + 9) * 5) `div` 100 - 1
Note the backticks (`), which allow a normal function to be used infix. You could write this as:
print $ (div ((((i * 5) + 6) * 4 + 9) * 5) 100) - 1
But then the brackets are making things really hard to read.
Are there any other solutions better than truncating by a divisor?
In general probably not, but as mentioned on your other question, this particular equation will always give you the same result as your input, so you can just write:
main = getLine >>= print
How can I remove digits at arbitrary positions?
Converting to a string and removing characters is likely your best bet. Something like the following will work, although it's arguably a bit dense:
removeDigits :: [Int] -> Int -> Int
removeDigits indices x = read . reverse . filterIndices indices . reverse . show $ x
filterIndices :: [Int] -> [a] -> [a]
filterIndices inds elems = map snd . filter ((`notElem` inds) . fst) . zip [1..] $ elems
Note this treats the last digit as the "1st" digit - it's a bit more natural to refer to digits with.
An (in my opinion) easier to read representation of your existing code is:
transform = (subtract 1) . (`quot` 100) . (*5) . (+9) . (*4) . (+6) . (*5)
With this way of writing it, composition overrides the arithmetic precedence laws, letting us write it how it's read ("times 5, add 6, times 4, ..."). We have to use subtract 1, as -1 is interpreted as the literal value -1, not as a unary function.
Removing digits at arbitrary positions is an interesting problem. This is probably easiest to do by converting to string and performing string manipulation, then reading back as an Int. Since Int implements both Show and Read, you can do:
type Digit = Int
removeDigits :: [Digit] -> Int -> Int
removeDigits digits = read . go 1 . show
where
go _ [] = []
go i (c:cs) | i `elem` digits = go cs (i+1)
| otherwise = c : go cs (i+1)
-- N.B. I chose 1-indexing here instead of 0-indexing because of your word choice
-- "remove the first, second, and sixth digits" maps naturally to [1, 2, 6],
-- though programmers may find that off-putting. YMMV.
removeDigits here could be re-written as
read [c | (i, c) <- zip [1..] (show n), i `notElem` digits]
Related
I have to write a simple pi approximation and I did and it works fine, but in the task it says to write a function with the header "pi_approx :: Int -> Double".
My code:
pi_approx x = sqrt (pi2_approx(x))
pi2_approx x =
if x/= 1
then (6 /(x*x)) + (pi2_approx(x-1))
else (6/(1*1))
However my function works fine without "pi_approx :: Int -> Double", but when i try to use this declaration I always get the type error:
pi_approx.hs:10:14: error:
Couldn't match expected type Double' with actual type Int'
In the expression: (+) (6 / (x * x)) (pi2_approx (x - 1))
In the expression:
if x /= 1 then
(+) (6 / (x * x)) (pi2_approx (x - 1))
else
(6 / (1 * 1))
In an equation for `pi2_approx':
pi2_approx x
= if x /= 1 then
(+) (6 / (x * x)) (pi2_approx (x - 1))
else
(6 / (1 * 1))
|
10 | then (+) (6 /(x*x)) (pi2_approx(x-1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I tried to use fromIntegral in various ways and if I run the function without declaration I checked the type of the solution, which is: "(Floating a, Eq a) => a"
As I understand Double should be an instance of Floating so I don´t understand why it wont compile.
I am very new at haskell and it seems I don´t understand the core concept of data types and constraints. I can´t seem to find any simple and good documentation/explanation on the topic though. Maybe someone here can help me understand based on this example :)
because x is an Int, hence x * x is also an Int, and you can not use an Int for (/) :: Floating a => a -> a -> a.
You need to convert this to a Double, for example with fromIntegral :: (Integral a, Num b) => a -> b:
pi2_approx :: Int -> Double
pi2_approx 1 = 6
pi2_approx x = 6 / fromIntegral (x*x) + pi2_approx (x-1)
For a large number of iterations, it gives a result close to π2:
Prelude> sqrt (pi2_approx 10000)
3.1414971639472147
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have a data type
data S = Fac S | Mul S S | Nat Integer
deriving (Show)
and a grammar defined as
S ::= S "!" | S "*" S | natural
So far I have this written
pa :: Parser S
pa = facst <|> multst <|> natst
facst = do
s <- pa
char '!'
return (Fac s)
multst = do
s1 <- pa
char '*'
s2 <- pa
return (Mul s1 s2)
natst = do
n <- natural
return (Nat n)
But facst and multst doesn't work. And natst only works with single integers like "5" but not "56".
I've tried doing
natst = do
n <- some natural
return (Nat n)
but that creates an error.
Could someone point me in the right direction?
As was suggested in several comments, your grammar is ambiguous and contains left-recursion and so is a problem for recursive-descent parsers like most parser combinator libraries generate. See e.g. the Q&As How to remove ambiguity in the following grammar? and Left recursion elimination for how to do this.
In your case,
S ::= S "!" | S "*" S | natural
has left-recursion because both the "!" and the "*" production begin with an S. It is ambiguous because it is unclear which of the S's should be derived first in the "*" production: Given an expression like 1 * 2 * 3, should this produce
* *
/ \ / \
1 * or * 3 ?
/ \ / \
2 3 1 2
1 * (2 * 3) (1 * 2) * 3
It is also ambiguous, as #melpomene points out, because 1 * 2 ! could produce
* !
/ \ |
1 ! or *
| / \
2 1 2
1 * (2 !) (1 * 2) !
An example of a rewritten grammar (there are others) that has neither left-recursion or ambiguities is:
S ::= natural S₁
S₁ ::= "!" | "*" S | ε
With this grammar, 1 * 2 * 3 will always parse as
S
1 S₁
1 * S
1 * 2 S₁
1 * 2 * S
1 * 2 * 3 S₁
1 * 2 * 3 ε
meaning * becomes right-associative. And 1 * 2 ! will always parse as
S
1 S₁
1 * S
1 * 2 S₁
1 * 2 !
meaning ! gets a higher precedence than *, which I don't know is good or bad.
Either way, if you want the parser to express arbitrary expressions, you probably want to extend the grammar with explicit parentheses so that you can override the default precedence of each operator.
As for the parser itself, you could model it directly on a rewritten grammar, e.g.:
parseS :: Parser S
parseS = do
n <- natural
f <- parseS1
return (f n)
natural :: Parser S
natural = do
n <- read <$> many1 digit
return (Nat n)
parseS1 :: Parser (S -> S)
parseS1 = parseFac <|> parseMul <|> parseNat
where
parseFac = do
char '!'
return (\s -> Fac s)
parseMul = do
char '*'
s2 <- parseS
return (\s1 -> Mul s1 s2)
parseNat = do
eof -- ε
return (\s -> s)
Then you'll have to deal with whitespace:
> parse parseS "" "1*2*3"
Right (Mul (Nat 1) (Mul (Nat 2) (Nat 3)))
> parse parseS "" "1 * 2 * 3"
Left (line 1, column 2):
unexpected ' '
expecting digit, "!", "*" or end of input
> parse parseS "" " 1*2*3"
Left (line 1, column 1):
unexpected " "
expecting digit
> parse parseS "" "1*2*3 "
Left (line 1, column 6):
unexpected ' '
expecting digit, "!", "*" or end of input
I'd consult a tutorial or a book on getting this part right.
Finally you may want to use some of the higher-level features of various parser combinator libraries like chainr1 or Text.Megaparsec.Expr's makeExprParser that try to deal with this kind of thing in a less bothersome way. Still, before using them, it is wise to understand how they're implemented by making parsers manually as an exercise like you're currently doing. For example, how would you transform the parser above so that "*" is left-associative or that "!" has a lower precedence?
I am doing some arbitrary operations in Haskell as I learn, and have been playing with a list of animals with certain properties, including age.
This is my script:
module Animals where
data Animal = CatThing String Int
| DogThing String Int
deriving Show
animalList :: [Animal]
animalList = [CatThing "Spot" 2, DogThing "Rex" 5]
-- write a function that returns the string component given an animal
getName :: Animal -> String
getName (CatThing name _) = name
getName (DogThing name _) = name
-- get the age of an animal (uses "map")
getAge :: Animal -> Int
getAge (CatThing _ age) = age
getAge (DogThing _ age) = age
-- sum age
sumAge :: Int -> [Int] -> Int
sumAge _ [b, c] = foldl (+) 0 [b, c]
-- average age
???
I am stuck on how to sum using foldl'. I know there is a sum function built in, but I am really trying to practice folds, so am trying to do it that way.
Does anyone have suggestions on how to proceed?
The code for your sum looks fine, I'd use foldl' instead of foldl so you don't risk a stack overflow, and also change that [b,c] pattern to a generic variable or even better point free so it looks better and it's also more general:
sumAge :: [Double] -> [Double]
sumAge = foldl' (+) 0
As for the average, you just sum and divide by the length:
averageAge :: [Double] -> Double
averageAge ls = sumAge ls / length ls
PS. In case your ages are integer, then the first function still works, but the average need to change:
averageInt :: [Int] -> Double
averageInt ls = (fromInteger . sum) ls / (fromInteger . length) ls
TL;DR version
Sum: sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
Average:
import Data.Sequence(foldlWithIndex, fromList)
average numbers = foldlWithIndex (\a i x -> let k = fromIntegral i in (k*a + x) / (k + 1)) 0 . fromList $ numbers
Long version
If you have an interest in math, it may help to understand the design of fold functions as equivalent to discovering sequence formulas by induction.
Sum
For sum, since you have s[i+1] = s[i] + x[i+1], you can simply use addition like you did, although you may have to convert before you add:
sumAges :: [Animal] -> Int
sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
sumAgesPointFree :: [Animal] -> Int
sumAgesPointFree = foldl (flip $ (+) . getAge) 0
Average
For example, one way to calculate the average of a list using a single fold function is to use a recursive mathematical version of calculating the rolling average of a sequence: m[i+1] = (i * m[i] + x[i+1]) / (i + 1). You can see this in how you calculate the average of lists of varying sizes:
{-
Not Haskell, just attempting mathematical notation without knowing MathML in Markdown.
m: mean or average
x: an element of a list or sequence
[]: subscript
-}
m[1] = x[1]
m[2] = (x[1] + x[2]) / 2 = (m[1] + x[2]) / 2 -- m[1] = x[1], so substitute
m[3] = (x[1] + x[2] + x[3]) / 3 -- (a+b)/n = a/n + b/n, so distribute
= (x[1] + x[2]) / 3 + x[3] / 3 -- a = n/n * a, n not in {0, Infinity}
= 2/2 * (x[1] + x[2]) / 3 + x[3] / 3 -- n/n * 1/a = n/a * 1/n
= 2/3 * (x[1] + x[2]) / 2 + x[3] / 3 -- m[2] = (x[1] + x[2])/2, so substitute
= 2/3 * m[2] + x[3] / 3
= 2*m[2] / 3 + x[3] / 3
= (2*m[2] + x[3]) / 3
...
m[i+1] = (i * m[i] + x[i+1]) / (i+1)
However, since this function would require the element index as a parameter, due to the List structure's lack of (convenient) indexing, the Sequence type from the Data.Sequence module may work out better than a List, especially considering the Data.Sequence module has this really nice foldlWithIndex function:
module Average(average) where
import Data.Sequence(foldlWithIndex, fromList)
average :: Fractional a => [a] -> a
average = foldlWithIndex averageByPrevious 0 . fromList
where averageByPrevious previous index current = (coefficient*previous + current) / (coefficient + 1)
where coefficient = fromIntegral index
Then you can simply run average list where list is some list you want to find the rolling average of. This is one way to calculate the average of a list using a single fold without adding a large performance overhead as you would by running multiple O(n) functions over the same list, even considering laziness as a benefit to the performance of multiple calls.
NOTE: I will admit, this is not easy to read, so average xs = (sum xs) / (length xs) as #Lorenzo said will work much better if legibility is more important than performance here.
I'm reading the Learn you some Haskell for the Greater Good book, as I was playing around with recursion in Haskell I implemented the fibonacci function, the recursive version is simple, probably can be improved:
-- recursive fibonacci numbers
rfib :: Int -> Int
rfib 0 = 0
rfib 1 = 1
rfib n = rfib (n-1) + rfib(n-2)
As I was googling to learn more I stumbled upon this article:
http://java.dzone.com/articles/what-fibonacci-taught-me-about
The author shows the fibonacci formula:
I decided to implement it in Haskell using rational numbers to avoid floating point imprecisions. My implementation looks like this:
fibMultiplier = (toRational 1) / (toRational (sqrt 5))
firstFibTerm n = (((toRational 1) + (toRational (sqrt 5))) / toRational 2) ^ n
secondFibTerm n = (((toRational 1) - (toRational (sqrt 5))) / toRational 2) ^ n
fib :: Int -> Int
fib n = truncate (fromRational (fibMultiplier * firstFibTerm n) - (fibMultiplier * secondFibTerm n))
As a beginner I am sure that the code above can be drastically improved, can you point me what can be improved or some mistakes I've made?
I apreciate the help.
UPDATE
So, after playing around with the suggestions, I found that using Data.Real.Constructible is fast and precise, with no rounding errors. My final implementation is:
fib :: Int -> Construct
fib n = ( ( (1 / (sqrt 5)) * ( (( 1 + (sqrt 5) ) / 2) ^ n ) ) -
( (1 / (sqrt 5)) * ( (( 1 - (sqrt 5) ) / 2) ^ n ) ) )::Construct
I also implemented a function that returns a list of the n fibonacci numbers:
fibList :: Int -> [Construct]
fibList n = [fib(x) | x <- [0..n]]
Using this function we can compare the results of the different implementations:
-- recursive fibonacci numbers
rfib :: Int -> Int
rfib 0 = 0
rfib 1 = 1
rfib n = rfib (n-1) + rfib(n-2)
-- recursive fibonacci sequence
rfibList :: Int -> [Int]
rfibList n = [rfib(x) | x <- [0..n]]
-- rfibList 20 returns: [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]
-----------------------------------
-- fibonacci number using Double and truncate
doubleFib :: Integer -> Integer
doubleFib n = truncate ( ( (1 / (sqrt 5)) * ( (( 1 + (sqrt 5) ) / 2) ^ n ) ) -
( (1 / (sqrt 5)) * ( (( 1 - (sqrt 5) ) / 2) ^ n ) ) )
-- fibonacci list using Double and truncate
doubleFibList :: Integer -> [Integer]
doubleFibList n = [doubleFib(x) | x <- [0..n]]
-- doubleFibList 20 returns: [0,1,0,2,3,5,8,13,21,34,55,89,143,232,377,610,986,1597,2584,4181,6764]
-----------------------------------
-- fibonacci number using Construct
constructFib :: Int -> Construct
constructFib n = ( ( (1 / (sqrt 5)) * ( (( 1 + (sqrt 5) ) / 2) ^ n ) ) -
( (1 / (sqrt 5)) * ( (( 1 - (sqrt 5) ) / 2) ^ n ) ) )::Construct
-- fibonacci list using construct
constructFibList :: Int -> [Construct]
constructFibList n = [constructFib(x) | x <- [0..n]]
-- constructFibList 20 returns: [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]
Notice that we get a rounding error on the doubleFibList, the 16th number should be 987 but we get 986. The recursive implementation is slow, the Double implementation is imprecise, but using Construct we can get a fast and precise fibonacci sequence, much better than my old implementation using toRational.
(You can't use your sqrt version, use Data.Real.Constructible instead)
import Data.Real.Constructible
fib :: Int -> Construct
fib n = (((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n)/sqrt(5)
Below I have defined a function that converts a list of base-3 digits to the corresponding numerical value. For example:
f "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0) = 19
f "12" = 5
f "1202" = 47
f "120221" = 430
Here is a definition using comprehension:
f :: String -> Int
f str = sum (listToFinal (stringToTuples str))
Helper functions:
-- 1) converts "201" to "102"
reverse "str"
-- 2) converts "102" to 102
stringToInt :: String -> Int
stringToInt str = read str :: Int
-- 3) converts 102 to ['1','0','2']
intToList :: Int -> [Int]
intToList 0 = []
intToList x = intToList (x `div` 10) ++ [x `mod` 10]
-- 4) converts "201" to [(1,0),(0,1),(2,2)] using reverse, stringToInt, intToList
stringToTuples :: String -> [(Int,Int)]
stringToTuples str = zip (intToList (stringToInt (reverse str))) [0..]
-- 5) converts [(1,0),(0,1),(2,2)] to [1*3^0, 0*3^1, 2*3^2]
listToFinal :: [(Int,Int)] -> [Int]
listToFinal list = [ x * (3^y) | (x,y) <- list ]
Now I'd like to do it with recursion only (well, using basic & library functions too, of course).
An idea: I was thinking of taking the head of each element in the list and simply multiplying it with 3^(length of string - 1). The only problem is, with each recursive call the power of three would have to decrease by 1, e.g. given:
recursive_version "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0)
How to implement this?
Here is a much simpler approach; note that, through the use of foldl, it's only "implicitly" recursive, though. For information, digitToInt is exported by Data.Char.
import Data.Char
import Data.List ( foldl' )
--- horner x xs : the value of polynomial 'xs' at point 'x'
horner :: Int -> [Int] -> Int
horner x = foldl' (\c1 c0 -> c1 * x + c0) 0
-- f s : the integer whose representation in base 3 is string 's'
f :: String -> Int
f = horner 3 . map digitToInt
When you define it recursively, the natural way to decrement the length is trimming the array from the head. For example:
base3 x = base3' x 0 where
base3' (d:ds) v = base3' ds $ v + d * 3 ^ length ds
base3' [] v = v