处理计算器程序中的令牌错误

如何解决处理计算器程序中的令牌错误

我正在尝试处理我用haskell制作的计算器程序中的令牌错误,我的代码如下:

import Data.Char
import Control.Applicative

data MayError a = Value a | Error String

instance (Show a) => Show (MayError a) where
  show (Value x) = show x
  show (Error s) = "error: " ++ s

instance Functor MayError where
  fmap f (Value x) = Value (f x)
  fmap f (Error s) = Error s

instance Applicative MayError where
  pure x = Value x
  (Value f) <*> (Value x) = Value (f x)
  (Value f) <*> (Error s) = Error s
  (Error s) <*> _ = Error s

instance Monad MayError where
  return x = Value x
  (Value x) >>= f = f x
  (Error s) >>= f = Error s

{- tokenizer -}
data Token = Num Int | Add | Sub | Mul | Div | Exp | LPar | RPar deriving (Eq,Show)

tokens :: String -> MayError [Token]
tokens [] = []
tokens ('+':cs) = Add:(tokens cs)
tokens ('-':cs) = Sub:(tokens cs)
tokens ('*':cs) = Mul:(tokens cs)
tokens ('/':cs) = Div:(tokens cs)
tokens ('(':cs) = LPar:(tokens cs)
tokens (')':cs) = RPar:(tokens cs)
tokens ('^':cs) = Exp:(tokens cs)
tokens (c:cs) | isDigit c = let (ds,rs) = span isDigit (c:cs)
                            in Num(read ds):(tokens rs)
              | isSpace c = tokens cs
              | otherwise = Error "unknown token"

{- parser -}
data ParseTree = Number Int |
                 Plus ParseTree ParseTree |
                 Minus ParseTree ParseTree |
                 Times ParseTree ParseTree |
                 Divide ParseTree ParseTree |
                 Power ParseTree ParseTree
                 deriving Show

type Parser = [Token] -> MayError(ParseTree,[Token])

parseFactor::Parser
parseFactor (Num x:l) = return (Number x,l)
parseFactor (Add:l) = parseFactor l
parseFactor (Sub:l) = let (p1,l1) = parseFactor l in (Minus (Number 0) p1,l1)
parseFactor (LPar:l) = let (p1,RPar:l1) = parseExpr l in (p1,l1)
parseFactor _ = Error "parse error"

parseExponent::Parser
parseExponent l = nextExp $ parseFactor l
  where nextExp(p1,Exp:l1) = let (p2,l2) = parseFactor l1
                              in nextExp(Power p1 p2,l2)
        nextExp x = x

parseTerm::Parser
parseTerm l = nextFactor $ parseExponent l
  where nextFactor(p1,Mul:l1) = let (p2,l2) = parseExponent l1
                                 in nextFactor(Times p1 p2,l2)
        nextFactor(p1,Div:l1) = let (p2,l2) = parseExponent l1
                                 in nextFactor(Divide p1 p2,l2)
        nextFactor x = x

parseExpr::Parser
parseExpr l = nextTerm $ parseTerm l
  where nextTerm(p1,Add:l1) = let (p2,l2) = parseTerm l1
                               in nextTerm(Plus p1 p2,l2)
        nextTerm(p1,Sub:l1) = let (p2,l2) = parseTerm l1
                               in nextTerm(Minus p1 p2,l2)
        nextTerm x = x

{- evaluator -}
eval::ParseTree -> MayError Int
eval (Number x) = Value x
eval (Plus p1 p2) = do x <- eval p1
                       y <- eval p2
                       return (x+y)
eval (Minus p1 p2) = do x <- eval p1
                        y <- eval p2
                        return (x-y)
eval (Times p1 p2) = do x <- eval p1
                        y <- eval p2
                        return (x*y)
eval (Divide p1 p2) = do x <- eval p1
                         y <- eval p2
                         if y == 0 then Error "division by 0" 
                                   else return (x `div` y)
eval (Power p1 p2) = do x <- eval p1
                        y <- eval p2
                        if y < 0 then Error "cannot process negative exponents"
                                 else return (x^y)

parse :: [Token] ->  MayError ParseTree
parse ts = do (pt,rs) <- parseExpr ts
              if null rs then return pt else Error "extra token"                                                                                                                                         

{- main -}
main = do cs <- getContents
          putStr $ unlines $ map show $
            map (\s -> tokens s >>= parse >>= eval) $ lines cs

当我不尝试解析错误时一切正常,但现在错误如下所示:

calc_final2.hs:29:13: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[a1]’
    • In the expression: []
      In an equation for ‘tokens’: tokens [] = []
   |
29 | tokens [] = []
   |             ^^

calc_final2.hs:30:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: Add : (tokens cs)
      In an equation for ‘tokens’: tokens ('+' : cs) = Add : (tokens cs)
   |
30 | tokens ('+':cs) = Add:(tokens cs)
   |                   ^^^^^^^^^^^^^^^

calc_final2.hs:30:24: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: Add : (tokens cs)
      In an equation for ‘tokens’: tokens ('+' : cs) = Add : (tokens cs)
   |
30 | tokens ('+':cs) = Add:(tokens cs)
   |                        ^^^^^^^^^

calc_final2.hs:31:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: Sub : (tokens cs)
      In an equation for ‘tokens’: tokens ('-' : cs) = Sub : (tokens cs)
   |
31 | tokens ('-':cs) = Sub:(tokens cs)
   |                   ^^^^^^^^^^^^^^^

calc_final2.hs:31:24: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: Sub : (tokens cs)
      In an equation for ‘tokens’: tokens ('-' : cs) = Sub : (tokens cs)
   |
31 | tokens ('-':cs) = Sub:(tokens cs)
   |                        ^^^^^^^^^

calc_final2.hs:32:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: Mul : (tokens cs)
      In an equation for ‘tokens’: tokens ('*' : cs) = Mul : (tokens cs)
   |
32 | tokens ('*':cs) = Mul:(tokens cs)
   |                   ^^^^^^^^^^^^^^^

calc_final2.hs:32:24: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: Mul : (tokens cs)
      In an equation for ‘tokens’: tokens ('*' : cs) = Mul : (tokens cs)
   |
32 | tokens ('*':cs) = Mul:(tokens cs)
   |                        ^^^^^^^^^

calc_final2.hs:33:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: Div : (tokens cs)
      In an equation for ‘tokens’: tokens ('/' : cs) = Div : (tokens cs)
   |
33 | tokens ('/':cs) = Div:(tokens cs)
   |                   ^^^^^^^^^^^^^^^

calc_final2.hs:33:24: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: Div : (tokens cs)
      In an equation for ‘tokens’: tokens ('/' : cs) = Div : (tokens cs)
   |
33 | tokens ('/':cs) = Div:(tokens cs)
   |                        ^^^^^^^^^

calc_final2.hs:34:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: LPar : (tokens cs)
      In an equation for ‘tokens’: tokens ('(' : cs) = LPar : (tokens cs)
   |
34 | tokens ('(':cs) = LPar:(tokens cs)
   |                   ^^^^^^^^^^^^^^^^

calc_final2.hs:34:25: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: LPar : (tokens cs)
      In an equation for ‘tokens’: tokens ('(' : cs) = LPar : (tokens cs)
   |
34 | tokens ('(':cs) = LPar:(tokens cs)
   |                         ^^^^^^^^^

calc_final2.hs:35:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: RPar : (tokens cs)
      In an equation for ‘tokens’: tokens (')' : cs) = RPar : (tokens cs)
   |
35 | tokens (')':cs) = RPar:(tokens cs)
   |                   ^^^^^^^^^^^^^^^^

calc_final2.hs:35:25: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: RPar : (tokens cs)
      In an equation for ‘tokens’: tokens (')' : cs) = RPar : (tokens cs)
   |
35 | tokens (')':cs) = RPar:(tokens cs)
   |                         ^^^^^^^^^

calc_final2.hs:36:19: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: Exp : (tokens cs)
      In an equation for ‘tokens’: tokens ('^' : cs) = Exp : (tokens cs)
   |
36 | tokens ('^':cs) = Exp:(tokens cs)
   |                   ^^^^^^^^^^^^^^^

calc_final2.hs:36:24: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens cs)’
      In the expression: Exp : (tokens cs)
      In an equation for ‘tokens’: tokens ('^' : cs) = Exp : (tokens cs)
   |
36 | tokens ('^':cs) = Exp:(tokens cs)
   |                        ^^^^^^^^^

calc_final2.hs:38:32: error:
    • Couldn't match expected type ‘MayError [Token]’
                  with actual type ‘[Token]’
    • In the expression: Num (read ds) : (tokens rs)
      In the expression:
        let (ds,rs) = span isDigit (c : cs) in Num (read ds) : (tokens rs)
      In an equation for ‘tokens’:
          tokens (c : cs)
            | isDigit c
            = let (ds,rs) = span isDigit (c : cs)
              in Num (read ds) : (tokens rs)
            | isSpace c = tokens cs
            | otherwise = Error "unknown token"
   |
38 |                             in Num(read ds):(tokens rs)
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^

calc_final2.hs:38:46: error:
    • Couldn't match expected type ‘[Token]’
                  with actual type ‘MayError [Token]’
    • In the second argument of ‘(:)’,namely ‘(tokens rs)’
      In the expression: Num (read ds) : (tokens rs)
      In the expression:
        let (ds,rs) = span isDigit (c : cs) in Num (read ds) : (tokens rs)
   |
38 |                             in Num(read ds):(tokens rs)
   |                                              ^^^^^^^^^

calc_final2.hs:56:38: error:
    • Couldn't match expected type ‘(a,b)’
                  with actual type ‘MayError (ParseTree,[Token])’
    • In the expression: parseFactor l
      In a pattern binding: (p1,l1) = parseFactor l
      In the expression:
        let (p1,l1)
    • Relevant bindings include
        p1 :: a (bound at calc_final2.hs:56:28)
        l1 :: b (bound at calc_final2.hs:56:32)
   |
56 | parseFactor (Sub:l) = let (p1,l1)
   |                                      ^^^^^^^^^^^^^

calc_final2.hs:56:55: error:
    • Couldn't match expected type ‘MayError (ParseTree,[Token])’
                  with actual type ‘(ParseTree,b0)’
    • In the expression: (Minus (Number 0) p1,l1)
      In the expression:
        let (p1,l1)
      In an equation for ‘parseFactor’:
          parseFactor (Sub : l)
            = let (p1,l1)
   |
56 | parseFactor (Sub:l) = let (p1,l1)
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^

calc_final2.hs:57:44: error:
    • Couldn't match expected type ‘(a,[Token])’
                  with actual type ‘MayError (ParseTree,[Token])’
    • In the expression: parseExpr l
      In a pattern binding: (p1,RPar : l1) = parseExpr l
      In the expression: let (p1,RPar : l1) = parseExpr l in (p1,l1)
    • Relevant bindings include p1 :: a (bound at calc_final2.hs:57:29)
   |
57 | parseFactor (LPar:l) = let (p1,l1)
   |                                            ^^^^^^^^^^^

calc_final2.hs:57:59: error:
    • Couldn't match expected type ‘MayError (ParseTree,[Token])’
                  with actual type ‘(a0,[Token])’
    • In the expression: (p1,l1)
      In the expression: let (p1,l1)
      In an equation for ‘parseFactor’:
          parseFactor (LPar : l)
            = let (p1,l1)
   |
57 | parseFactor (LPar:l) = let (p1,l1)
   |                                                           ^^^^^^^^

calc_final2.hs:61:19: error:
    • Couldn't match expected type ‘MayError (ParseTree,[Token])’
    • In the expression: nextExp $ parseFactor l
      In an equation for ‘parseExponent’:
          parseExponent l
            = nextExp $ parseFactor l
            where
                nextExp (p1,Exp : l1) = let ... in nextExp (Power p1 p2,l2)
                nextExp x = x
   |
61 | parseExponent l = nextExp $ parseFactor l
   |                   ^^^^^^^^^^^^^^^^^^^^^^^

calc_final2.hs:61:29: error:
    • Couldn't match expected type ‘(ParseTree,[Token])’
    • In the second argument of ‘($)’,namely ‘parseFactor l’
      In the expression: nextExp $ parseFactor l
      In an equation for ‘parseExponent’:
          parseExponent l
            = nextExp $ parseFactor l
            where
                nextExp (p1,l2)
                nextExp x = x
   |
61 | parseExponent l = nextExp $ parseFactor l
   |                             ^^^^^^^^^^^^^

calc_final2.hs:62:46: error:
    • Couldn't match expected type ‘(a,[Token])’
    • In the expression: parseFactor l1
      In a pattern binding: (p2,l2) = parseFactor l1
      In the expression:
        let (p2,l2) = parseFactor l1 in nextExp (Power p1 p2,l2)
    • Relevant bindings include
        p2 :: a (bound at calc_final2.hs:62:36)
        l2 :: b (bound at calc_final2.hs:62:40)
   |
62 |   where nextExp(p1,l2) = parseFactor l1
   |                                              ^^^^^^^^^^^^^^

calc_final2.hs:67:15: error:
    • Couldn't match expected type ‘MayError (ParseTree,[Token])’
    • In the expression: nextFactor $ parseExponent l
      In an equation for ‘parseTerm’:
          parseTerm l
            = nextFactor $ parseExponent l
            where
                nextFactor (p1,Mul : l1) = let ... in nextFactor (Times p1 p2,l2)
                nextFactor (p1,Div : l1)
                  = let ... in nextFactor (Divide p1 p2,l2)
                nextFactor x = x
   |
67 | parseTerm l = nextFactor $ parseExponent l
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

calc_final2.hs:67:28: error:
    • Couldn't match expected type ‘(ParseTree,namely ‘parseExponent l’
      In the expression: nextFactor $ parseExponent l
      In an equation for ‘parseTerm’:
          parseTerm l
            = nextFactor $ parseExponent l
            where
                nextFactor (p1,l2)
                nextFactor x = x
   |
67 | parseTerm l = nextFactor $ parseExponent l
   |                            ^^^^^^^^^^^^^^^

calc_final2.hs:68:48: error:
    • Couldn't match expected type ‘(a,[Token])’
    • In the expression: parseExponent l1
      In a pattern binding: (p2,l2) = parseExponent l1
      In the expression:
        let (p2,l2) = parseExponent l1 in nextFactor (Times p1 p2,l2)
    • Relevant bindings include
        p2 :: a (bound at calc_final2.hs:68:39)
        l2 :: b (bound at calc_final2.hs:68:42)
   |
68 |   where nextFactor(p1,l2) = parseExponent l1
   |                                                ^^^^^^^^^^^^^^^^

calc_final2.hs:70:48: error:
    • Couldn't match expected type ‘(a,l2) = parseExponent l1 in nextFactor (Divide p1 p2,l2)
    • Relevant bindings include
        p2 :: a (bound at calc_final2.hs:70:39)
        l2 :: b (bound at calc_final2.hs:70:42)
   |
70 |         nextFactor(p1,l2) = parseExponent l1
   |                                                ^^^^^^^^^^^^^^^^

calc_final2.hs:75:15: error:
    • Couldn't match expected type ‘MayError (ParseTree,[Token])’
    • In the expression: nextTerm $ parseTerm l
      In an equation for ‘parseExpr’:
          parseExpr l
            = nextTerm $ parseTerm l
            where
                nextTerm (p1,Add : l1) = let ... in nextTerm (Plus p1 p2,l2)
                nextTerm (p1,Sub : l1) = let ... in nextTerm (Minus p1 p2,l2)
                nextTerm x = x
   |
75 | parseExpr l = nextTerm $ parseTerm l
   |               ^^^^^^^^^^^^^^^^^^^^^^

calc_final2.hs:75:26: error:
    • Couldn't match expected type ‘(ParseTree,namely ‘parseTerm l’
      In the expression: nextTerm $ parseTerm l
      In an equation for ‘parseExpr’:
          parseExpr l
            = nextTerm $ parseTerm l
            where
                nextTerm (p1,l2)
                nextTerm x = x
   |
75 | parseExpr l = nextTerm $ parseTerm l
   |                          ^^^^^^^^^^^

calc_final2.hs:76:46: error:
    • Couldn't match expected type ‘(a,[Token])’
    • In the expression: parseTerm l1
      In a pattern binding: (p2,l2) = parseTerm l1
      In the expression:
        let (p2,l2) = parseTerm l1 in nextTerm (Plus p1 p2,l2)
    • Relevant bindings include
        p2 :: a (bound at calc_final2.hs:76:37)
        l2 :: b (bound at calc_final2.hs:76:40)
   |
76 |   where nextTerm(p1,l2) = parseTerm l1
   |                                              ^^^^^^^^^^^^

calc_final2.hs:78:46: error:
    • Couldn't match expected type ‘(a,l2) = parseTerm l1 in nextTerm (Minus p1 p2,l2)
    • Relevant bindings include
        p2 :: a (bound at calc_final2.hs:78:37)
        l2 :: b (bound at calc_final2.hs:78:40)
   |
78 |         nextTerm(p1,l2) = parseTerm l1
   |                                              ^^^^^^^^^^^^

我真正想做的是在输入一些无效令牌时让我的程序显示“未知令牌”。

解决方法

由于tokens的返回类型是MayError [Token],所以需要将项目包裹在Value中,对于我们递归的项目,我们可以执行一个fmap来附加到包含在 Value 中的列表:

tokens :: String -> MayError [Token]
tokens [] = Value []
tokens ('+':cs) = (Add:) <$> tokens cs
tokens ('-':cs) = (Sub:) <$> tokens cs
tokens ('*':cs) = (Mul:) <$> tokens cs
tokens ('/':cs) = (Div:) <$> tokens cs
tokens ('(':cs) = (LPar:) <$>  tokens cs
tokens (')':cs) = (RPar:) <$>  tokens cs
tokens ('^':cs) = (Exp:) <$>  tokens cs
tokens (c:cs) | isDigit c = let (ds,rs) = span isDigit (c:cs)
                            in (Num (read ds):) <$> tokens rs
              | isSpace c = tokens cs
              | otherwise = Error "unknown token"

其他函数也有同样的问题:您应该将值包装在 Value 数据构造函数中,或者如果您正在处理 MayError 值,则将它们解开包装。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res