Reputation: 181
I'm trying to learn how to use Haskell and now I have to make a program that takes a integer n and a string k and every letter of that string will be moved n places to the right in the alphabet. At this moment I've got the next code:
import Data.Char
main = do
x <- read getLine :: Int
y <- getLine
caesar x y
result :: String
rotate :: Int -> Char -> [Char]
rotate a b = [chr ((a + ord b) `mod` ord 'z' + ord 'a')]
caesar :: Int -> String -> ()
caesar moving text= do
rotatespecific moving text 0
putStrLn result
rotatespecific :: Int -> String -> Int -> ()
rotatespecific moving text place = do
if place < length text
then
result ++ rotate (moving (text !! place))
rotatespecific (moving text (place + 1))
else
if place == length text
then
result ++ rotate (moving (text !! place))
But I can't compile it because it still gives me the same error message:
parse error (possibly incorrect indentation or mismatched brackets)
|
28 | result ++ rotate (moving (text !! place))
| ^
But I can't see what's wrong with my syntax. I first thought it had something to do with using a Char as parameter for my function but I was wrong because text !! place should give a char and not a [char]. So what's wrong with what I'm doing?
After some edit I got this, but it still doesn't work:
import Data.Char
main = do
xr <- getLine
let x = read xr :: Int
y <- getLine
putStrLn (rotatespecific (x y 0))
rotate :: Int -> Char -> [Char]
rotate a b = [chr ((a + ord b) `mod` ord 'z' + ord 'a')]
rotatespecific :: Int -> String -> Int -> String
rotatespecific moving text place = do
if place < length text
then do
help <- text !! place
h <- rotate (moving help)
a <- rotatespecific (moving text (place + 1))
b <- h ++ a
return b
else
if place == length text
then do
return rotate (moving (text !! place))
else
return ()
Upvotes: 1
Views: 639
Reputation: 60463
I feel like this is an appropriate time to just show an example, because there are a lot of little problems. I'm not going to fix logic bugs, but I've fixed your syntax. Hopefully this gets you unstuck.
rotatespecific :: Int -> String -> Int -> String
rotatespecific moving text place =
if place < length text then
-- use let .. in instead of do/bind (<-) in pure functions.
let help = text !! place
-- multiple arguments are given after the function, no parentheses
h = rotate moving help
-- use parentheses around an argument if it is a complex expression
-- (anything more than a variable name)
a = rotatespecific moving text (place+1)
b = h ++ a
in b
else
if place == length text then
rotate moving (text !! place)
else
undefined -- you must decide what String to return in this case.
After you have this function working as intended, and only then, open this sealed envelope. ♥️
rotatespecific :: Int -> String -> String rotatespecific moving text = concatMap (rotate moving) text
Upvotes: 0
Reputation: 60463
The immediate problem is that every if
must have an else
. You got a parse error at the end because the parser is expecting more, namely an else
for that if place == length text
.
When you fix this you will have more problems, because you are treating Haskell like an imperative language, and that's not how she likes to be treated. It seems like you think
result ++ newstuff
will mutate result
, adding newstuff
to the end of it. But Haskell doesn't mutate. Instead, this expression result ++ newstuff
is the list that results when you concatenate result
and newstuff
, but result
itself remains unchanged.
ghci> let result = [1,2,3]
ghci> result ++ [4,5,6]
[1,2,3,4,5,6]
ghci> result
[1,2,3]
rotatespecific
must return the rotated string, rather than trying to mutate it into existence. The only way functions may communicate is by returning results computed from their arguments -– they may not manipulate any "global" state like result
. A function that returns ()
is guaranteed to be useless.
rotatespecific :: Int -> String -> Int -> String
Delete the result
"global variable" (which does not mean what you think it means) and focus on defining rotatespecific
in a way that it returns the rotated string.
I would also recommend commenting out main
and caesar
for now until you have rotatespecific
compiling and working when you test it in ghci
.
Upvotes: 4