解析错误:(错误的缩进或错误的括号)

时间:2015-01-07 19:50:05

标签: parsing haskell ghc

我开始学习Haskell。即使我是一个非凡的笨蛋,我也打算做这项工作。我收到的错误列为标题。这是我编写的代码,用于尝试实现复制列表(n)次并将其新长度连接为新列表的行为。现在我基本了解了解析在Haskell中是如何工作的,在我的原始代码下面,我将给出一些修改过的代码示例,看看我对解析的理解是否足够。我现在的问题是如何正确地缩进或构造我的块以便不接收此错误(这是特定的:O) - 在创建实例和格式时,我是否缺少一些信息?如果您注意到我的当前实体或主要功能是完全错误的,请不要告诉我或提出建议。我想弄明白,并且当我到达它时将处理GHC错误。 (我希望这是正确的学习方式)。但是,如果我可以请求任何人的帮助来解决理解正确格式的第一个障碍,我将不胜感激。

module Main where 
import Data.List

n :: Int 
x :: [Char]

instance Data stutter n x where
   x = []
   n = replicate >>=  x : (n:xs)
   stutter >>= main = concat [x:xs]

let stutter 6 "Iwannabehere"  -- <-- parse error occurs here!!!

- 使用适当的括号修改代码,至少在我认为它们去的地方。

module Main where 
import Data.List

n :: Int 
x :: [Char]

instance Data stutter n x where{
   ;x = []
   ;n = replicate >>=  x : (n:xs)
   ;stutter >>= main = concat [x:xs]
;
};let stutter 6 "Iwannabehere" -- there should be no bracket of any kind at the end of this

我将'let'表达式放在块的外部,我不相信它会进入内部,如果我这样做,我也会收到解析错误。不对,但我想我还是会问。

2 个答案:

答案 0 :(得分:5)

我不确定instance Data stutter n x应该是什么,instance XYZ where语法仅用于类型类,但是这里有几个语法错误。

首先,虽然GHC表示错误发生在let stutter 6 "Iwannabehere",但您的第一个错误发生在stutter >>= main = concat [x:xs]之前。单个=符号保留用于分配,这仅仅是定义。您可以在顶级,where块内或let块内部进行分配(where包括类型类实例定义)。您无法将作业作为x >>= y = z等表达式的一部分。

您的下一个语法错误是let本身。 let块不能出现在顶层,它们只出现在另一个定义中。您在GHCi中使用let但其原因超出了本答案的范围。可以说在GHCi中输入表达式并不等同于源文件的顶级。

接下来,如果你在某个地方使用let块,它只能包含定义。语法看起来更像

let <name> [<args>] = <definition>
    [<name> [<args>] = <definition>]
in <expression>

这整个块表达了。例如,你可以写

def f(x, y, z):
    w = x + y + z
    u = x - y - z
    return w * u
在Python中

,这相当于Haskell函数定义

f x y z = let w = x + y + z
              u = x - y - z
          in w * u

它只定义局部变量。当您在do块中使用它时,还有另一种形式,您可以在其中排除in <expression>部分,例如

main = do
    name <- getLine
    let message = if length name > 5 then "short name" else "long name"
        goodbye n = putStrLn ("Goodbye, " ++ n)
    putStrLn message
    goodbye name

请注意,此处无需使用in。你可以根据需要,只是意味着你必须开始一个新的do块:

main = do
    name <- getLine
    let message = ...
        goodbye n = ...
    in do
        putStrLn message
        goodbye name

这并不是那么漂亮。

希望这会使您更加注重正确的语法,但看起来您对Haskell的工作方式存在一些误解。你看过Learn You a Haskell吗?它是一种非常温和而有趣的语言介绍,可以真正帮助您学习语法和核心思想。

答案 1 :(得分:1)

您的解析错误来自let关键字。删除它,不会发生与此相关的错误。 let x = y仅与GHCi和do - 块有关,此时两者都不相关。基本上,只需用这一行替换它:

theWordIGet = stutter 6 "Iwannabehere"

其次,Haskell中的instance关键字 absolutley nothing 与您在此阶段要执行的操作有关。这不是Haskell函数的定义方式,而是我猜你想做的事情。这是您想要创建stutter函数的假设,假设它只是重复字符串n次。

stutter :: Int -> String -> String
stutter n x = concat (replicate n x)

您还要删除(超出范围)值nx的类型声明:它们不是对象,它们是&#d;函数的参数,它有自己的签名,用于确定函数调用中nx的类型。

最后,我想你会在程序执行时打印stutter 6 "Iwannabehere"的值。要做到这一点,只需添加:

main :: IO ()
main = print (stutter 6 "Iwannabehere")

总之,我恳求你从头开始并阅读“了解你的哈斯克尔”#39;在线here,因为您完全走错了方向 - 您引用的程序是可以具有意义的混乱表达,但是在错误的地方。本书将向您展示Haskell的语法,我在这一个答案中可以写得更好,并将完全解释如何使您的程序以您期望的方式运行。