如何在Haskell的另一个函数中将函数的结果用作变量?

时间:2019-11-24 17:10:06

标签: haskell

我正在尝试学习如何使用Haskell,现在我必须编写一个程序,该程序需要一个整数n和一个字符串k,并且该字符串的每个字母都将在字母表的右侧移动n个位置。此时,我有了下一个代码:

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))

但是我无法编译它,因为它仍然给我同样的错误消息:

parse error (possibly incorrect indentation or mismatched brackets)
   |
28 |                     result ++ rotate (moving (text !! place))
   |                                                              ^

但是我看不出语法有什么问题。我首先认为这与将Char作为函数的参数有关,但我错了,因为文本!地方应该给一个字符而不是一个[字符]。那我在做什么呢?

经过一些编辑后,我得到了它,但是仍然不起作用:

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 ()

2 个答案:

答案 0 :(得分:5)

直接的问题是,每个if必须具有一个else 。最后,您遇到了解析错误,因为解析器期望的更多,即该else的{​​{1}}。

解决此问题时,您会遇到更多问题,因为您将Haskell当作命令式语言对待,而这并不是她喜欢被对待的方式。好像你在想

if place == length text

将变异result ++ newstuff ,并在其末尾添加result。但是Haskell不会变异。相反,此表达式newstuff是将result ++ newstuffresult连接在一起时得到的列表,但是newstuff本身保持不变。

result

ghci> let result = [1,2,3] ghci> result ++ [4,5,6] [1,2,3,4,5,6] ghci> result [1,2,3] 必须返回旋转后的字符串,而不是试图将其变异为存在。函数进行通信的唯一方法是返回从其参数计算得出的结果-它们不能操纵任何rotatespecific之类的“全局”状态。返回result的函数被保证是无用的。

()

删除rotatespecific :: Int -> String -> Int -> String “全局变量”(这并不意味着您所认为的意思),并专注于以返回旋转字符串的方式定义result

我还建议暂时注释掉rotatespecificmain,直到在caesar中测试rotatespecific为止。{p}

答案 1 :(得分:0)

我觉得这是一个展示示例的适当时机,因为存在很多小问题。我不会修复逻辑错误,但已经修复了您的语法。希望这能使您摆脱困境。

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.

使此功能正常工作后,然后再打开此密封的信封。 ♥️

  

 rotatespecific :: Int -> String -> String
 rotatespecific moving text = concatMap (rotate moving) text