首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell - Happy -“没有实例...”错误

Haskell - Happy -“没有实例...”错误
EN

Stack Overflow用户
提问于 2013-05-28 02:24:15
回答 1查看 208关注 0票数 1

我正在尝试熟悉Haskell的Happy解析器生成器。目前,我有一个来自文档的示例,但是当我编译程序时,我得到一个错误。代码如下:

代码语言:javascript
复制
{
module Main where
import Data.Char
}

%name calc
%tokentype { Token }
%error { parseError }

%token 
      let             { TokenLet }
      in              { TokenIn }
      int             { TokenInt $$ }
      var             { TokenVar $$ }
      '='             { TokenEq }
      '+'             { TokenPlus }
      '-'             { TokenMinus }
      '*'             { TokenTimes }
      '/'             { TokenDiv }
      '('             { TokenOB }
      ')'             { TokenCB }

%%

Exp   : let var '=' Exp in Exp  { \p -> $6 (($2,$4 p):p) }
      | Exp1                    { $1 }

Exp1  : Exp1 '+' Term           { \p -> $1 p + $3 p }
      | Exp1 '-' Term           { \p -> $1 p - $3 p }
      | Term                    { $1 }

Term  : Term '*' Factor         { \p -> $1 p * $3 p }
      | Term '/' Factor         { \p -> $1 p `div` $3 p }
      | Factor                  { $1 }

Factor                    
      : int                     { \p -> $1 }
      | var                     { \p -> case lookup $1 p of
                                    Nothing -> error "no var"
                                    Just i  -> i }
      | '(' Exp ')'             { $2 }

{
parseError :: [Token] -> a
parseError _ = error "Parse error"

data Token
      = TokenLet
      | TokenIn
      | TokenInt Int
      | TokenVar String
      | TokenEq
      | TokenPlus
      | TokenMinus
      | TokenTimes
      | TokenDiv
      | TokenOB
      | TokenCB
 deriving Show

lexer :: String -> [Token]
lexer [] = []
lexer (c:cs) 
      | isSpace c = lexer cs
      | isAlpha c = lexVar (c:cs)
      | isDigit c = lexNum (c:cs)
lexer ('=':cs) = TokenEq : lexer cs
lexer ('+':cs) = TokenPlus : lexer cs
lexer ('-':cs) = TokenMinus : lexer cs
lexer ('*':cs) = TokenTimes : lexer cs
lexer ('/':cs) = TokenDiv : lexer cs
lexer ('(':cs) = TokenOB : lexer cs
lexer (')':cs) = TokenCB : lexer cs

lexNum cs = TokenInt (read num) : lexer rest
      where (num,rest) = span isDigit cs

lexVar cs =
   case span isAlpha cs of
      ("let",rest) -> TokenLet : lexer rest
      ("in",rest)  -> TokenIn : lexer rest
      (var,rest)   -> TokenVar var : lexer rest

main = getContents >>= print . calc . lexer
}

我得到了这个错误:

代码语言:javascript
复制
[1 of 1] Compiling Main             ( gr.hs, gr.o )

gr.hs:310:24:
No instance for (Show ([(String, Int)] -> Int))
  arising from a use of `print'
Possible fix:
  add an instance declaration for (Show ([(String, Int)] -> Int))
In the first argument of `(.)', namely `print'
In the second argument of `(>>=)', namely `print . calc . lexer'
In the expression: getContents >>= print . calc . lexer

你知道为什么和如何解决它吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-28 02:44:16

如果您检查错误消息

代码语言:javascript
复制
No instance for (Show ([(String, Int)] -> Int))
  arising from a use of `print'

很明显,问题在于您正在尝试print一个函数。实际上,解析器函数calc生成的值应该是一个接受变量绑定的查找表并返回结果的函数。例如,请参阅变量规则:

代码语言:javascript
复制
{ \p -> case lookup $1 p of
    Nothing -> error "no var"
    Just i  -> i }

因此,在main中,我们需要为p参数传入一个列表,例如一个空列表。(如果需要,您也可以添加一些预定义的全局变量)。我已经将无指针的代码扩展为do块,以便更容易地看到发生了什么:

代码语言:javascript
复制
main = do
  input <- getContents
  let fn = calc $ lexer input
  print $ fn [] -- or e.g. [("foo", 42)] if you wanted it pre-defined

现在它可以工作了:

代码语言:javascript
复制
$ happy Calc.y
$ runghc Calc.hs <<< "let x = 1337 in x * 2"
2674
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16778624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档