我很开心使用这种新语言,除非有时难以排除故障。
这是我的教授想要的,他希望我接受用户的数字并计算一个正在运行的平均值。
现在到目前为止,这是我所拥有的,除了我的基本编程为某些类型错误提供错误。
我是Comp Sci的学生,这是一个我自己想要做的作业。
module Main (listM, main) where
import System.IO
import Data.List
listM = [1, 2, 3]
main = do
average listM = realToFrac (sum listM) / genericLength listM
putStrLn (show(listM))
现在我有这个错误,让我发疯...:S Q1.hs:12:18:输入'='
时解析错误答案 0 :(得分:3)
很高兴听到你学习Haskell很开心!
就你的任务而言:你根本没有做坏事。我会说:你快到了。
正如Dwilson在他的优秀答案中解释的那样,编译器拒绝你的程序的原因是你的listM
的定义是在导入之前放的。在Haskell模块中,您总是从模块头开始(有时在一些编译指示之前)和导入列表,然后是函数的定义:
module Main (main) where
import System.IO
import Data.List
...
现在,您提到编译器(或可能是解释器)由于“类型错误”而拒绝您的程序。但是你得到的实际上是一个“解析错误”。理解两者之间的区别并不会有害:
当编译器处理你的程序时,它首先会检查你的程序 程序在语法上是正确的。如果不是,它将进行解析 你错了。
然后,它会检查您是否在一致的情况下使用您的功能, 即,它检查类型是否正确。如果他们不是,你 将面临类型错误。
通常,第一类错误很容易处理:编译器几乎总是指向程序中的位置,如果你犯了错误或输入错误(在你的情况下:第一个import语句)。第二类错误有时候处理起来比较棘手 - 但是成为一名优秀的Haskell程序员需要熟悉类型系统,并真正理解那里发生了什么(而不仅仅是尝试一下,直到它或多或少有效......)不过不用担心:它并不像你想象的那么难。
看看你的代码,让我觉得你定义了
average xs = realToFrac (sum listM) / genericLength listM
也就是说,您将average
定义为带参数xs
的函数,但您未在右侧使用xs
- 你的定义的一面。 xs
应该是您计算平均值的列表吗?在您的代码中,无论您提供哪个列表作为listM
的参数,您的函数始终会计算修订列表average
的平均值。除此之外,你的功能还可以。
现在,您唯一需要做的就是如何提示用户输入以及如何从该输入中构建数字列表。
祝你好运 - 玩得开心! ;)答案 1 :(得分:2)
就输入错误而言,因为import System.IO
在import Data.List
之前缩进。在Haskell中,缩进很重要,但如果您愿意,可以使用花括号和分号。任何缩进比前一行更远的行都算作该行的延续,因此ghc将您的文件解释为listM = [1, 2, 3] import System.IO
。
现在,如果这是你需要帮助的唯一的东西,那么玩Haskell吧!但是,如果您需要有关结构的帮助,您应该澄清您正在寻找的内容。你描述了教授想要什么以及你期望发生什么并不匹配。具体来说,教授说你应该从用户那里得到数字,这通常意味着你将在命令行提示他们,但是你说你希望程序将listM
中未输入的数字相加。用户。它是哪一个?
修改强>
更新以反映当前状态parse error on '='
。
GHC的错误起初可能令人生畏,但我发现当你习惯它们时,它们实际上比其他语言更有帮助。别担心你会到达那里!现在这个错误告诉你的是GHC在点击=
行average listM = realToFrac (sum listM) / genericLength listM
时不知道该怎么办。这是因为它将其视为main = do
行的延续,并且在do
块中,所有与=
的绑定必须使用let
语句完成,如下所示: let average listM = realToFrac (sum listM) / genericLength listM
。现在这可能不是你想要的,因为你的函数average
只能在do块中使用!您应该做的是在average
块之外定义do
,然后在do
块内的某个位置调用它。
几个指针:
ParseError
通常意味着你的代码语法错误。遇到问题时应该做的第一件事是检查缩进,然后检查是否缺少括号,括号等。let
和=
用于绑定非 monadic的内容,例如let x = length "foobar"
<-
运算符用于绑定monadic事物,例如x <- getChar