This question already has an answer here:
Haskell (n+1) in pattern matching
(1 answer)
Closed 6 years ago.
I am a student learning Haskell. My textbook gives the following as an example:
(*) :: Int -> Int -> Int
m * 0 = 0
m * (n + 1) = m + (m * n)
It then asks us to redefine the ^ (positive integral exponentiation) operator in the same manner for an exercise. I assumed the following would work:
(^) :: Int -> Int -> Int
m ^ 0 = 1
m ^ (n + 1) = m * (m ^ n)
However, it fails to compile, giving a 'parse error in pattern' on the (n + 1) bit. Out of curiosity, I tried the multiplication operator as defined in the book's example, and it gave the same error.
Where/how is the textbook wrong, and how do I correct it?
Edit
Thank you to those who pointed out that this issue was addressed some years ago. Since the "feature" of n+k pattern matching was removed, how would I modify the textbook example to follow modern good practice?
In short, I now know why the original does not work, but how could it be changed to work?
You just replace n with n-1 on both sides of the equation:
(*) :: Int -> Int -> Int
m * 0 = 0
m * ((n-1) + 1) = m + (m * (n-1))
which is not valid syntax, but of course "simplifies" to the correct version
(*) :: Int -> Int -> Int
m * 0 = 0
m * n = m + (m * (n-1))
If you prefer not using the NPlusKPatterns extension then you can write:
import Prelude hiding ((^))
(^) :: Int -> Int -> Int
m ^ 0 = 1
m ^ n = m * (m ^ (n - 1))
The line import Prelude hiding ((^)) avoids the duplicate definition of (^), since it is already defined in Prelude.
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
I am trying to finish up a simple homework assignment in Haskell for a class at my university, but I cannot figure out why my code won't compile:
-- Comments
module Main where
main :: IO ()
main = do
n <- readLn
print (fac n)
print (facList n)
print (sumFacs n)
print (fibonacci n)
-- Aufgabe 2 (a):
fac :: Int -> Int
let
fac 0 = 1
fac i = i * fac(i - 1)
-- Aufgabe 2 (b):
facList :: Int -> Int -> [Int]
let
facList x y = [fac m | m <- [x..y]]
sumFacs :: Int -> Int -> Int
let
sumFacs x y = sum (facList x y)
-- Aufgabe 3:
fibonacci :: Int -> Int
let
fibonacci 0 = 1
fibonacci 1 = 1
fibonacci i = fibonacci (i - 1) + fibonacci (i - 2)
When I attempt to compile the above code using the Glasgow compiler, I get the following error message:
Uebung01.hs:19:1: error:
parse error (possibly incorrect indentation or mismatched brackets)
|
19 | facList :: Int -> Int -> [Int]
| ^
All of the functions work in interactive mode. Sorry for posting such a simple question, but I am completely new to Haskell and am really struggling to understand how the whitespace rules work. I have looked at answers to similar questions, but I'm still unable to find my mistake. Thanks for reading.
A let block [Haskell-report] expects an in to specify expression. In your fac function you define a let block, but without an in, this is used to define locally scoped variable(s) that you can then use in the in clause. You however do not need a let here, you can define fac as:
fac :: Int -> Int
fac 0 = 1
fac i = i * fac (i - 1)
You need to refactor other functions in a similar manner.
This Haskell program prints "1.0" How can I get it to print "1"?
fact 0 = 1
fact x = x * fact (x-1)
place m n = (fact m) / (fact n) * (fact (m-n))
main = do
print (place 0 0)
By using the / operation, you are asking haskell to use a fractional data type. You probably don't want that in this case. It is preferable to use an integral type such as Int or Integer. So I suggest to do the following:
1. Add a type declaration for the fact function, something like fact :: Integer -> Integer
2. Use quot instead of /.
So your code should look like this:
fact :: Integer -> Integer
fact 0 = 1
fact x = x * fact (x-1)
place :: Integer -> Integer -> Integer
place m n = (fact m) `quot` (fact n) * (fact (m-n))
main = do
print (place 0 0)
Also, as #leftaroundabout pointed out, you probably want to use a better algorithm for computing those binomial numbers.
You could just use round:
print (round $ place 0 0)
This changes the formatting to the one you want. redneb's answer is, however, the right approach.
I have this code to work out the sum of squares of integers in the range of m:n
sumsquares :: Integral a=> Int -> Int -> Int -> Int
sumsquares m n middle
| m > n = error "First number cannot be bigger than second number"
|m==n = m*m
|otherwise = m*m + sumsquares (m+1)n
How would i redefine the function sumsquares for this purpose?
If there is more than one number in the range m:n, compute the middle of the range and add the sum of the squares of (m:middle) to sum of the squares (middle+1:n),
otherwise there is only one number in the range m:n, so m = = n, and the solution is just the square of m. (Note that with this approach the recursion combines two half- solutions: each sub-problem is approximately half in size of the overall problem).
In your original function, the class constraint Integral a in the type signature is obsolete (a is not mentioned anywhere else in the signature, is it?). Furthermore, the third parameter of the function (middle) remains unused. Hence, you could have written it as
sumsquares :: Int -> Int -> Int
sumsquares m n
| m > n = error "First number cannot be bigger than second number"
| m == n = m * m
| otherwise = m * m + sumsquares (m + 1) n
Rewriting it to move from a decrease-and-conquer scheme to a strict divide-and-conquer scheme then just involves adapting the recursive case accordingly:
sumsquares :: Int -> Int -> Int
sumsquares m n
| m > n = error "First number cannot be bigger than second number"
| m == n = m * m
| otherwise = let middle = (m + n) `div` 2
in sumsquares m middle + sumsquares (middle + 1) n
The question remains, of course, why you would want to make this change. One reason could be that you are preparing your algorithm to be adapted for parallelisation: then, indeed, divide-and-conquer is often a better fit than decrease-and-conquer.
The Following code:
unSum :: Float -> Float
unSum x = (y + y`mod`2 + 2) / 2
where
y = x*(x+1) / 2
gives me this error when I try to load it into WinHugs 98:
Hugs> :load "D:\\kram\\unSumme2.hs"
ERROR file:.\unSumme2.hs:2 - Instance of Integral Float required for definition of unSumme2
What's the essence of this and how am I to do it? Anyway, I dont now if it serves my porpuse, I want to calculate the sum of the uneven numbers until x without recursivity.
It's because you're using mod. The definition of mod, from the Standard Prelude:
class (Real a, Enum a) => Integral a where
[...]
div, mod :: a -> a -> a
[...]
n `mod` d = r where (q,r) = divMod n d
In other words, it expects a to be of the numeric typeclass Integral, which includes only whole numbers.
If you want to stick with Floats, try using mod', from Data.Fixed, per this answer.
Alternatively, if you just want to do integer division, you could change your function's signature to
unSum :: Int -> Int
or similar.