来自类型匹配的混淆错误(我认为)- Haskell

Confusing Error from type matching (I think) - Haskell

收到一个错误,我无法理解

基本上我的程序应该对自定义数据类型执行操作'Config'

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) 以及为什么我的配置元组的第三个值与其他值不一样?

如有任何帮助,我们将不胜感激!

iexec :: Instr -> Config -> Config

好的,所以 iexec 有两个参数,returns 一个 Config (一个元组)。

iexec (LOADI n) c = do 

哦,但这说 iexec 有两个参数和 returns 形式为 Monad m => m a 的东西(通常是初学者的 IO,但并非总是如此)。

你不想在这里使用 do 符号 - 你根本不是在进行单子操作,只是一个纯粹的非单子计算。为此,如果您需要中间值,则应使用 let ... in ... ;如果不需要,则应使用结果表达式:

iexec :: Instr -> Config -> Config
iexec (LOADI n) (x,y,z) = (x+1, y, x)

或考虑等效的:

iexec :: Instr -> Config -> Config
iexec (LOADI n) (x,y,z) =
    let newPC = x+1
        newState = y
        newStack = x
    in (newPC, newState, newStack)

当然不,newStackx 根本不起作用,因为 Stack 不是 Int,但这只是与您的原始代码匹配。