【发布时间】:2022-01-22 08:53:59
【问题描述】:
遇到一个我无法理解的错误
基本上我的程序应该对自定义数据类型“配置”执行操作
type Vname = String
type Val = Int
type State = [(Vname, Val)]
data Instr =
LOADI Int
| LOAD Val
| ADD
| STORE Val
| JMP Int
| JMPLESS Int
| JMPGE Int
deriving (Eq, Read, Show)
data Stack = Stack [Int]
type Config = (Int, State, Stack)
iexec :: Instr -> Config -> Config
iexec (LOADI n) c = do {
(x,y,z) <- c
;return ( x+1, y, x )
}
我只尝试执行“LOADI”指令之一,但无论我如何更改,我都会收到错误:
• Couldn't match expected type ‘Stack’
with actual type ‘(c1, b0, c0)’
• In the pattern: (x, y, z)
In a stmt of a 'do' block: (x, y, z) <- c
In the expression:
do (x, y, z) <- c
return (x + 1, y, x)
|
42 | (x,y,z) <- c
| ^^^^^^^
Stack 只是一个 Int 的列表,但我必须以这种方式实现它
什么是 (c1, b0, c0),为什么我的配置元组的第三个值与其他值不一样?
任何帮助将不胜感激!
乔
【问题讨论】:
-
您的问题是使用 do 表示法,但实际上并未使用 monad。
do ...和let ... in ...你明白吗? -
您正在使用单子
do表示法,但您的类型不涉及任何单子。解决方案:不要使用do,不要使用return,以及任何其他与monad 相关的东西。例如,iexec (LOADI n) (x,y,z) =(x+1,y,z)类型检查并接近您的代码。 (不过,我认为这不是您真正需要的) -
更令人困惑的是
(Int, State, Stack)有一个Monad实例,它使s <- c成为一种提取堆栈组件的方法元组。 -
@chepner 好点,但我认为这失败了,因为
Int不是一个幺半群。这无助于生成良好的错误消息。 -
是的,
Stack与(x, y, z)的匹配失败首先发生,所以这就是你得到错误的地方。