Where is the indentation/layout error in my Haskell code? - haskell

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.

Related

Haskell: Difference between "(Int a, Bool b) => a -> b" and Int -> Bool [duplicate]

I wrote my first program in Haskell today. It compiles and runs successfully. And since it is not a typical "Hello World" program, it in fact does much more than that, so please congrats me :D
Anyway, I've few doubts regarding my code, and the syntax in Haskell.
Problem:
My program reads an integer N from the standard input and then, for each integer i in the range [1,N], it prints whether i is a prime number or not. Currently it doesn't check for input error. :-)
Solution: (also doubts/questions)
To solve the problem, I wrote this function to test primality of an integer:
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
It works great. But my doubt is that the first line is a result of many hit-and-trials, as what I read in this tutorial didn't work, and gave this error (I suppose this is an error, though it doesn't say so):
prime.hs:9:13:
Type constructor `Integer' used as a class
In the type signature for `is_prime':
is_prime :: Integer a => a -> Bool
According to the tutorial (which is a nicely-written tutorial, by the way), the first line should be: (the tutorial says (Integral a) => a -> String, so I thought (Integer a) => a -> Bool should work as well.)
is_prime :: (Integer a) => a -> Bool
which doesn't work, and gives the above posted error (?).
And why does it not work? What is the difference between this line (which doesn't work) and the line (which works)?
Also, what is the idiomatic way to loop through 1 to N? I'm not completely satisfied with the loop in my code. Please suggest improvements. Here is my code:
--read_int function
read_int :: IO Integer
read_int = do
line <- getLine
readIO line
--is_prime function
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
main = do
n <- read_int
dump 1 n
where
dump i x = do
putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
if i >= x
then putStrLn ("")
else do
dump (i+1) x
You are misreading the tutorial. It would say the type signature should be
is_prime :: (Integral a) => a -> Bool
-- NOT Integer a
These are different types:
Integer -> Bool
This is a function that takes a value of type Integer and gives back a value of type Bool.
Integral a => a -> Bool
This is a function that takes a value of type a and gives back a value of type Bool.
What is a? It can be any type of the caller's choice that implements the Integral type class, such as Integer or Int.
(And the difference between Int and Integer? The latter can represent an integer of any magnitude, the former wraps around eventually, similar to ints in C/Java/etc.)
The idiomatic way to loop depends on what your loop does: it will either be a map, a fold, or a filter.
Your loop in main is a map, and because you're doing i/o in your loop, you need to use mapM_.
let dump i = putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
in mapM_ dump [1..n]
Meanwhile, your loop in is_prime is a fold (specifically all in this case):
is_prime :: Integer -> Bool
is_prime n = all nondivisor [2 .. n `div` 2]
where
nondivisor :: Integer -> Bool
nondivisor i = mod n i > 0
(And on a minor point of style, it's conventional in Haskell to use names like isPrime instead of names like is_prime.)
Part 1: If you look at the tutorial again, you'll notice that it actually gives type signatures in the following forms:
isPrime :: Integer -> Bool
-- or
isPrime :: Integral a => a -> Bool
isPrime :: (Integral a) => a -> Bool -- equivalent
Here, Integer is the name of a concrete type (has an actual representation) and Integral is the name of a class of types. The Integer type is a member of the Integral class.
The constraint Integral a means that whatever type a happens to be, a has to be a member of the Integral class.
Part 2: There are plenty of ways to write such a function. Your recursive definition looks fine (although you might want to use n < i * i instead of n < 2 * i, since it's faster).
If you're learning Haskell, you'll probably want to try writing it using higher-order functions or list comprehensions. Something like:
module Main (main) where
import Control.Monad (forM_)
isPrime :: Integer -> Bool
isPrime n = all (\i -> (n `rem` i) /= 0) $ takeWhile (\i -> i^2 <= n) [2..]
main :: IO ()
main = do n <- readLn
forM_ [1..n] $ \i ->
putStrLn (show (i) ++ " is a prime? " ++ show (isPrime i))
It is Integral a, not Integer a. See http://www.haskell.org/haskellwiki/Converting_numbers.
map and friends is how you loop in Haskell. This is how I would re-write the loop:
main :: IO ()
main = do
n <- read_int
mapM_ tell_prime [1..n]
where tell_prime i = putStrLn (show i ++ " is a prime? " ++ show (is_prime i))

Haskell: why is failing with equals symbols?

I'm having an issue that is frustrating me a bit. I have the next really simple code:
describe "functions" $ do
it "can create a function" $ do
mysum :: a -> a
let mysum x = x + 1
mysum 5
But is not compiling, the error I'm having is:
error: Variable not in scope: mysum :: a -> a
|
15 | mysum :: a -> a
From the books I'm reading seems everything fine to me, and in internet seems that shouldn't fail my code, am I missing something?
Also I tried more alternatives:
let b = mysum :: a -> a
let b x = x + 1
b 5
And
let b = a -> a
let b x = x + 1
b 5
But in all of them I have errors
To define a function with a signature in a do-block, you need to put both its signature and its definition inside the same let. Indentation matters. For instance,
example = do
something1
something2
let mysum :: Num a => a -> a
mysum x = x + 1 -- same indentation as "mysum" above
something3 -- we can use mysum here
something4
Concretely:
describe "functions" $ do
it "can create a function" $ do
let mysum :: Num a => a -> a
mysum x = x + 1
mysum 5 `shouldBe` (6 :: Int)
The above declares a polymorphic mysum, as you tried to do. If we instead define a more basic mysum :: Int -> Int, we do not need to specify that 6 is an Int in the very last line, since that's already deduced.

Parse Error In Pattern for Recursive Mathematical Operators [duplicate]

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.

Haskell multiple arguments function

myfunc:: [Int] -> Int -> Int
myfunc mylist i =
if length(mylist) == 0 then 1
else
(head(mylist) * i) + myfunc((tail(mylist)) (i+1))
I want to get a weighted sum over a list.
for example, at given parameter [10,9,8,7,6] and 1,
I want to get 10*1 + 9*2 + 8*3 + 7*4 + 6*5 ..
But my code puts error that
test.hs:9:18: error:
• Couldn't match expected type ‘Int’ with actual type ‘Int -> Int’
how to fix this problem??
you should check your parentheses - you use much more of them then you need to (leading to the problem here)
If you look at myfunc((tail(mylist)) (i+1)) then if you count the (..) you will see that the one argument to myfunc here is tail(mylist) (i+1) but this would mean that you try to apply (i+1) to tail(mylist)
Also instead of the check with length and head you can use pattern-matching.
here is a cleaned up version of your function:
myfunc :: [Int] -> Int -> Int
myfunc [] _ = 1
myfunc (h:tl) i = h*i + myfunc tl (i+1)
which will return 111 for your example:
> myfunc [10,9,8,7,6] 1
111
I don't know how much you've seen of Haskell but you can express this as
myfunc :: [Int] -> Int -> Int
myfunc weights start = 1 + sum (zipWith (*) weights [start..])
too - which I would consider more readable and idiomatic
Also: - why the 1 if the list is empty? Shouldn't your weighted sum be 0 if the list is empty??

Haskell State monadic function using recursion

TL:DR: Is there a way to do example 3 without passing an argument
I'm trying to understand the state monad in haskell (Control.Monad.State). I made an extremely simple function:
Example 1
example :: State Int Int
example = do
e <- get
put (e*5)
return e
This example works in ghci...
runState example 3
(3,15)
I modified it to be able to take arguments....
Example 2
example :: Int -> State Int Int
example n = do
e <- get
put (e*n)
return e
also works in ghci...
runState (example 5) 3
(3,15)
I made it recursive, counting the number of steps it takes for a computation to satisfy some condition
Example 3
example :: Int -> State Int Int
example n = do
e <- get
if (n /= 1)
then do
put (succ e)
example (next n)
else return (succ e)
next :: Int -> Int
next n
| even n = div n 2
| otherwise = 3*n+1
ghci
evalState (example 13) 0
10
My question is, is there a way to do the previous example without explicitly passing a value?
You can store n in the state along side of e, for example, something like:
example = do
(e,n) <- get
if n /= 1
then do put (succ e, next n); example
else return e
There is some overhead to using the State monad, so you should compare this with the alternatives.
For instance, a more Haskelly way of approaching this problem is compose list operations to compute the answer, e.g.:
collatz :: Int -> [Int]
collatz n = iterate next n
collatzLength n = length $ takeWhile (/= 1) $ collatz n

Resources