Trying to understand indentations in haskell - haskell

I am trying to make a program that solves the tower of hanoi. I made it a bit complicated just for exercise:
hanoi :: [Int] -> String
hanoi n
| n > 0 = hanoi' n "1" "2" "3"
where hanoi' n a b c
| n == 0 = "|"
| otherwise = let pre = hanoi' (n-1) a c b
posle = hanoi' (n-1) b c a
in pre ++ a ++ " ~~> " ++ c ++ posle
| otherwise = "Number must be greater than 0!!!"
But i get:
hanoi.hs:7:97: parse error on input ‘=’
Can someone please explain to me what is going on? I see now that i don't understand an important part of the language.

Your where has to come after all guards.
hanoi :: [Int] -> String
hanoi n
| n > 0 = hanoi' n "1" "2" "3"
| otherwise = "Number must be greater than 0!!!"
where hanoi' n a b c
| n == 0 = "|"
| otherwise = let pre = hanoi' (n-1) a c b
posle = hanoi' (n-1) b c a
in pre ++ a ++ " ~~> " ++ c ++ posle
This is stated in 4.4.3, although it's somewhat hidden if you're not used to BNF-like syntax:
decl → (funlhs | pat) rhs
funlhs → var apat { apat }
| pat varop pat
| ( funlhs ) apat { apat }
rhs → = exp [where decls]
| gdrhs [where decls]
gdrhs → guards = exp [gdrhs]
guards → | guard1, …, guardn (n ≥ 1)
guard → pat <- infixexp (pattern guard)
| let decls (local declaration)
| infixexp (boolean guard)
rhs is the important token. It's the only part that contains the optional where. A guard may only contain expressions and be followed by other guards.

Related

An haskell "exp" function returns a wrong result

the following code:
Module Main where
main :: IO ()
main = do putStrLn "hello"
putStrLn $ "2 exp 6 = " ++ show (2 `exp1` 6)
exp1 :: Integer -> Integer -> Integer
exp1 x n | n == 0 = 1
| n == 1 = x
| even n = exp1 (x*x) m
| odd n = x * exp1 (x*x) (m-1)
where m = n `div` 2
produces the output 4 for 2 `exp1` 6, which is obviously wrong.
thanks
The odd case is wrong. You end up evaluating exp1 4 3 to be 4 * (exp1 16 0).

Why does the following code not parse?

The following code does not parse:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
print $ result
where result = last [1..1000000]
The compiler complains on the second print:
src/Main.hs:10:5: parse error on input `print'
Why is this?
The problem is that where clauses can be attached to bindings only, not to expressions.
In fact:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
is exactly equivalent to:
main :: IO ()
main = do
print $ result
where result = foldl' (+) 0 [1..1000000]
i.e. the where defines local definitions for main not for the print $ result line.
Since where must be the last part of a binding obviously the following print expression causes a syntax error.
To use a where inside a do-block you have to use it when defining the let bindings such as this (very silly example):
main = do
let result = f
where f = foldl' (+) 0 [1..1000000]
print result
You can check this in the grammar:
decl → gendecl
| (funlhs | pat) rhs
rhs → = exp [where decls]
| gdrhs [where decls]
Note that the where decls is part of the rhs rule which defines the right hand side of a declaration. If you check the rules for exp you wont find where mentioned:
exp → infixexp :: [context =>] type (expression type signature)
| infixexp
infixexp → lexp qop infixexp (infix operator application)
| - infixexp (prefix negation)
| lexp
lexp → \ apat1 … apatn -> exp (lambda abstraction, n ≥ 1)
| let decls in exp (let expression)
| if exp [;] then exp [;] else exp (conditional)
| case exp of { alts } (case expression)
| do { stmts } (do expression)
| fexp
fexp → [fexp] aexp (function application)
aexp → qvar (variable)
| gcon (general constructor)
| literal
| ( exp ) (parenthesized expression)
| ( exp1 , … , expk ) (tuple, k ≥ 2)
| [ exp1 , … , expk ] (list, k ≥ 1)
| [ exp1 [, exp2] .. [exp3] ] (arithmetic sequence)
| [ exp | qual1 , … , qualn ] (list comprehension, n ≥ 1)
| ( infixexp qop ) (left section)
| ( qop⟨-⟩ infixexp ) (right section)
| qcon { fbind1 , … , fbindn } (labeled construction, n ≥ 0)
| aexp⟨qcon⟩ { fbind1 , … , fbindn } (labeled update, n ≥ 1)

Convert a Haskell function to SML

I'm trying to convert a Haskell function, which displays a boolean formula, to a SML function.
The function:
data Formula
= Atom String
| Neg Formula
| Conj Formula Formula
| Disj Formula Formula
precedence :: Formula -> Int
precedence Atom{} = 4
precedence Neg {} = 3
precedence Conj{} = 2
precedence Disj{} = 1
displayPrec :: Int -> Formula -> String
displayPrec dCntxt f = bracket unbracketed where
dHere = precedence f
recurse = displayPrec dHere
unbracketed = case f of
Atom s -> s
Neg p -> "~ " ++ recurse p
Conj p q -> recurse p ++ " & " ++ recurse q
Disj p q -> recurse p ++ " | " ++ recurse q
bracket
| dCntxt > dHere = \s -> "(" ++ s ++ ")"
| otherwise = id
display :: Formula -> String
display = displayPrec 0
I' ve come so far as translating it to SML:
fun precedence(operator) =
case operator of
Atom a => 4
| Neg p => 3
| Conj(p,q) => 2
| Disj(p,q) => 1
fun displayPrec dCntxt f =
let
val dHere = precedence f
val recurse = displayPrec dHere
val unbracketed = case f of
Atom a => a
| Neg p => "~ " ^ recurse p
| Conj(p,q)=>(recurse p) ^ " & " ^ (recurse q)
| Disj(p,q)=>(recurse p) ^ " | " ^ (recurse q)
(* missing bracket function *)
in
(* bracket *) unbracketed
end
The unbracketed function works. It shows the formula without braces. The only thing that is still missing is the bracket function, which I don't know what it does and how to translate it to SML. Can someone, who is more experienced, help me with this?
That would be
val bracket =
if dCntxt > dHere
then fn s => "(" ^ s ^ ")"
else fn x => x
The function compares the precedence level of your context against the precedence level of the outer operator of your expression and decides to either insert a pair of parentheses around the given string or not.

Haskell syntax for 'or' in case expressions

In F#, I can use | to group cases when pattern matching. For example,
let rec factorial n =
match n with
| 0 | 1 -> 1 // like in this line
| _ -> n * factorial (n - 1)
What's the Haskell syntax for the same?
There is no way of sharing the same right hand side for different patterns. However, you can usually get around this by using guards instead of patterns, for example with elem.
foo x | x `elem` [A, C, G] = ...
| x `elem` [B, D, E] = ...
| otherwise = ...
with guards:
factorial n
| n < 2 = 1
| otherwise = n * (factorial (n - 1))
with pattern matching:
factorial 0 = 1
factorial 1 = 1
factorial n = n * (factorial (n - 1))
I'm not entirely familiar with F#, but in Haskell, case statements allow you to pattern match, binding variables to parts of an expression.
case listExpr of
(x:y:_) -> x+y
[x] -> x
_ -> 0
In the theoretical case that Haskell allowed the same:
It would therefore be problematic to allow multiple bindings
case listExpr of
(x:y:_) | [z] -> erm...which variables are bound? x and y? or z?
There are rare circumstances where it could work, by using the same binding:
unEither :: Either a a -> a
unEither val = case val of
Left v | Right v -> v
And as in the example you gave, it could work alright if you only match literals and do not bind anything:
case expr of
1 | 0 -> foo
_ -> bar
However:
As far as I know, Haskell does not have syntax like that. It does have guards, though, as mentioned by others.
Also note:
Using | in the case statement serves a different function in Haskell. The statement after the | acts as a guard.
case expr of
[x] | x < 2 -> 2
[x] -> 3
_ -> 4
So if this sort of syntax were to be introduced into Haskell, it would have to use something other than |. I would suggest using , (to whomever might feel like adding this to the Haskell spec.)
unEither val = case val of
Left v, Right v -> v
This currently produces "parse error on input ,"
Building on some of the above answers, you can (at least now) use guards to do multiple cases on a single line:
case name of
x | elem x ["Bob","John","Joe"] -> putStrLn "ok!"
"Frank" -> putStrLn "not ok!"
_ -> putStrLn "bad input!"
So, an input of "Bob", "John", or "Joe" would give you an "ok!", whereas "Frank" would be "not ok!", and everything else would be "bad input!"
Here's a fairly literal translation:
factorial n = case n of
0 -> sharedImpl
1 -> sharedImpl
n -> n * factorial (n - 1)
where
sharedImpl = 1
View patterns could also give you a literal translation.
isZeroOrOne n = case n of
0 -> True
1 -> True
_ -> False
factorial1 n = case n of
(isZeroOrOne -> True) -> 1
n -> n * factorial (n - 1)
factorial2 n = case n of
(\n -> case n of { 0 -> True; 1 -> True; _ -> False }) -> 1
n -> n * factorial (n - 1)
Not saying that these are better than the alternatives. Just pointing them out.

How to check that I'm dealing with a list in Haskell?

I'm learning Haskell, and I'm trying to add preconditions to a (trivial, as an exercise) element_at function (code below). I've created a "helper" elem_at_r because otherwise, len x fails at some point (when x is a 'literal' rather than a list? - I still have trouble parsing ghci's error messages). elem_at now has all the error checking, and elem_at_r does the work. In elem_at, I'd like to add a check that x is indeed a list (and not a 'literal'). How can I do that?
len x = sum [ 1 | a <- x]
elem_at_r x n | n == 0 = head x
| 0 < n = elem_at_r (tail x) (n-1)
elem_at x n | x == [] = error "Need non-empty list"
| len x <= n = error "n too large " ++ show (len x)
| n < 0 = error "Need positive n"
| otherwise = elem_at_r x n
Thanks!
Frank
Due to Haskell's type system, elem_at can only take a list as its first argument (x); if you try to pass a non-list, GHC will detect this and give an error at compile time (or interpretation time in GHCi). I don't know why len would "fail"; could you post the error message that GHCi gives you?
It looks like you were getting errors because of the "x == []" line. The code below pattern matches for that condition and adds a few signatures. Otherwise it is the same. Hope it helps.
len x = sum [ 1 | a <- x]
elem_at_r :: [a] -> Int -> a
elem_at_r x n | n == 0 = head x
| 0 < n = elem_at_r (tail x) (n-1)
elem_at :: [a] -> Int -> a
elem_at [] _ = error "Need non-empty list"
elem_at x n | len x <= n = error ("n too large " ++ show (len x))
| n < 0 = error "Need positive n"
| otherwise = elem_at_r x n
You could also make your helper functions part of this function using a where clause:
elem_at :: [a] -> Int -> a
elem_at [] _ = error "Need non-empty list"
elem_at x n | len x <= n = error ("n too large " ++ show (len x))
| n < 0 = error "Need positive n"
| otherwise = elem_at_r x n
where
len :: [a] -> Int
len x = sum [ 1 | a <- x]
elem_at_r :: [a] -> Int -> a
elem_at_r x n | n == 0 = head x
| 0 < n = elem_at_r (tail x) (n-1)

Resources