Haskell ';输入上的分析错误';结合案例分析
我有下面的主要功能,它应该要求两个玩家提供他们的牌组,这些牌组是从另一个文件中的牌组库中选择的,然后使用这些输入运行一个循环Haskell ';输入上的分析错误';结合案例分析,haskell,Haskell,我有下面的主要功能,它应该要求两个玩家提供他们的牌组,这些牌组是从另一个文件中的牌组库中选择的,然后使用这些输入运行一个循环 main :: IO() main = do { putStr "Player1 choose deck\n"; d1 <- getLine; case d1 of { "deck1" -> let {d1 = deck1};
main :: IO()
main = do {
putStr "Player1 choose deck\n";
d1 <- getLine;
case d1 of
{
"deck1" -> let {d1 = deck1};
_ -> putStr "error"
};
putStr "Player2 choose deck\n";
d2 <- getLine;
case d2 of
{
"deck1" -> let {d2 = deck1};
_ -> putStr "error"
};
loop d1 d2
}
我已经盯着它看了很久了,我相信它很简单,但我希望有一双新的眼睛来看看到底出了什么问题。:) Haskell的
let
在do
块中的行为与在do
块外的行为不同。语句,let{d2=deck 1}
格式不正确,因为语法是let-in
。要解决此问题,可以将其包装在do
(例如:do-let{d2=deck1};
)中,这样可以解决解析错误,但这不是您想要的
OP中的代码有太多错误,我不确定从何处开始,但这里有一些提示:
- 什么是1/2
- d1/2的类型是什么?最初,它是一个字符串,因为您用
填充它,但随后您将它分配给getLine
,这可能不是一个字符串deck1
外部let
符号必须跟随do
<代码>让绑定不是一个值,它本身没有任何意义。此外,let绑定入值
仅在值中应用绑定let BINDING in VALUE
的do
的特殊之处在于它将绑定应用于它后面的所有行,但该绑定不会被覆盖。(例如:let
实际上只是do{let x=”“;putStrLn x}
(或者可能是pure”“>=\x->putStrLn x
,或者可能是return”“>=\x->putStrLn x
)(\x->putStrLn x)”
尝试完全避免do符号,我认为您会感到困惑,因为do符号允许Haskell看起来像Java一样是命令式的,但Haskell不是Java。您应该从更纯的代码开始,然后再探索Monad(和IO)在那之后。只有到那时你才能真正理解
do
那么let
语句的作用域通常是局部的。你不能“重新分配”(事实上,你一开始就不能分配)一个变量。所以这不起作用。您正试图在命令式编程中使用let x=…
作为赋值,但Haskell不是命令式的,并且没有赋值。let
可以定义局部变量,当作用域关闭时这些变量就会消失。如果您的代码是Java,则大致读取为if(…){int d1=;}else{int d2=…;}loop(d1,d2);
将触发一个未定义的变量错误。下面的问题是苏格拉底式的,有启发性的;我希望你能带着这种动机来阅读和思考它。你认为d1
应该在putStr“Player2 choose-deck\n”
这行中有什么类型的“deck1"
或deck1
的类型?为什么?Haskell使用缩进来表示块结构;通常,由于某种原因,只有当您想在同一行或数据
声明中填充所有内容时,才使用花括号和分号。请尝试去掉花括号和分号。@PaulJohnson,但大括号除外分号在这篇文章中是正确的…问题在于其他地方。因此,我的想法是有多个数据组可用,但是我只创建了一个,因此仅出于测试目的,d1
和d2
都应该是deck1
deck1
存储在一个绝望的文件中,并且具有[(String,Int,Int)
。我想要实现的是,在游戏开始之前,也就是在循环之前,玩家被问到他们想要使用哪一副牌,然后游戏开始时使用那些选定的牌。
"deck1" -> let {d1 = deck1};
"deck1" -> let {d2 = deck1};