我正在制作小语言

时间:2016-03-04 23:22:56

标签: haskell logging

我正在制作小语言。设E是一种很小的编程语言,支持算术表达式的声明和整数的相等比较。

给出以下数据类型E:

data E = IntLit Int
   | BoolLit Bool
   | Plus E E
   | Minus E E
   | Multiplies E E
   | Exponentiate E E
   | Equals E E
     deriving (Eq, Show)

这是我的代码,上面的数据正在运行所有这些。

data E = IntLit Int
   | BoolLit Bool
   | Plus E E
   | Minus E E
   | Multiplies E E
   | Divides E E
   | Equals E E
   | log2Sim E E        
     deriving (Eq, Show)
eval :: E -> E
eval c@(IntLit i) = c
eval c@(BoolLit b) = c
eval (Plus a b) = plus (eval a) (eval b)
eval (Minus a b) = minus (eval a) (eval b)
eval (Multiplies a b) = multiplies (eval a) (eval b)
eval (Divides a b) = divides (eval a) (eval b)
eval (Equals a b) = equals (eval a) (eval b)

log2Sim :: E -> E
log2sim  = case (eval x) of 
  IntLit i -> IntLit (logBase 2 i)
  x1 -> "type error: can't take the log of a non-IntLit-valued   expresstio" ++ show x1

plus (IntLit i) (IntLit j) = IntLit $ i + j
plus _ _ = error "Type error in addition"

minus (IntLit i) (IntLit j) = IntLit $ i - j
minus _ _ = error "Type error in subtraction"

multiplies (IntLit i) (IntLit j) = IntLit $ i * j
multiplies _ _ = error "Type error in multiplication"

divides (IntLit i) (IntLit j) = IntLit $ i `div` j
divides _ _ = error "Type error in division"

equals (IntLit i) (IntLit j) = BoolLit $ i == j
equals (BoolLit a) (BoolLit b) = BoolLit $ a == b
equals _ _ = error "Type error in equals"

当我编译它时,有一些错误。 这是什么错误?

A3.hs:56:7:
Couldn't match expected type `E' against inferred type `[Char]'
In the expression:
      "type error: can't take the lof of a non-IntLit-valued expression: "
    ++
      show x1
In a case alternative:
    x1
      -> "type error: can't take the lof of a non-IntLit-valued expression: "
       ++
         show x1
In the expression:
    case (eval x) of
      IntLit i -> IntLit (logBase 2 i)
      x1
        -> "type error: can't take the lof of a non-IntLit-valued expression: "
         ++
           show x1

1 个答案:

答案 0 :(得分:4)

您的代码中存在许多问题:

  1. 所有构造函数必须以大写字母开头。所以data E = ... | log2Sim E E不正确。你也可能只想要一个E,因此例如data E = ... | Log E可以解决这两个问题。
  2. 您声明了log2Sim但定义了log2sim(请注意大小写的差异)。您还忘记在定义中的x左侧写入参数=。通过编写

    来解决这两个问题
    log2Sim x = ...
    
  3. 字符串不是E类型的有效表达式。您可能希望通过调用error将错误字符串转换为E来遵循代码其余部分中的模式。因此:

    x1 -> error $ "type error: can't take the log of a non-IntLit-valued   expresstio" ++ show x1
    
  4. logBaseFloating点数进行操作,Int不是一个。有几种方法可以解决这个问题,但是这里和那里之间的最短距离是转换为Double并返回。例如:

    IntLit i -> IntLit . floor . logBase 2 . fromIntegral $ i
    
  5. 这足以使您的代码编译,但可能存在其他问题。