我将如何实现这种情况的CallE,它将具有用于测试函数调用的输入方?

问题描述 投票:0回答:2

我在某些Haskell上有所改进,但一直试图编写用于测试数学和关系的语言的解释器而陷入困境。除了CallE,我已经测试了所有数据类型的情况。我相信我必须使用Haskell中的map字符串方法创建一个新环境并映射值,但我不知道它的外观。对不起,我的英语不是我最好的语言!

// --------------- Declarations ----------------
data Expr = 
    IntE Integer
  | PlusE Expr Expr 
  | TimesE Expr Expr
  | BoolE Bool
  | IfE Expr Expr Expr
  | VarE String
  | LetE String Expr Expr
  | CallE String [Expr]
  deriving (Eq,Ord,Show)

data Command =
    DefC String [String] Expr
  deriving (Eq,Ord,Show)

data Program =
    Program [Command] Expr
  deriving (Eq,Ord,Show)

data Value = 
    IntV Integer
  | BoolV Bool
  deriving (Eq,Ord,Show)

data Answer = 
    ValueA Value
  | BadA
  deriving (Eq,Ord,Show)

type Env = Map String Value
type FEnv = Map String ([String],Expr)


// --------------- Helper functions ----------------

interpExprMany :: FEnv -> Env -> [Expr] -> Maybe [Value]
interpExprMany fenv env es = case es of
  [] -> Just []
  e:es' -> case interpExpr fenv env e of
    ValueA v -> case interpExprMany fenv env es' of
      Just vs -> Just (v:vs)
      Nothing -> Nothing
    BadA -> Nothing


extendEnvMany :: [String] -> [Value] -> Env -> Maybe Env
extendEnvMany as bs env = case (as, bs) of
  (as1:ass1, bs2:bss2) -> extendEnvMany ass1 bss2 (Map.insert as1 bs2 env)
  ([], []) -> Just env


// --------------- Implementation of interpreter----------------

interpExpr :: FEnv -> Env -> Expr -> Answer
interpExpr fenv env e = case e of

  IntE i -> ValueA (IntV i)
  BoolE b -> ValueA (BoolV b)

  PlusE e1 e2 -> case (interpExpr fenv env e1,interpExpr fenv env e2) of
    (ValueA (IntV i1),ValueA (IntV i2)) -> ValueA (IntV (i1 + i2))
    _ -> BadA

  IfE e1 e2 e3 -> case interpExpr fenv env e1 of
    ValueA (BoolV b) ->
      if b 
      then interpExpr fenv env e2
      else interpExpr fenv env e3

  VarE x -> case Map.lookup x env of
    Just v -> ValueA v
...
...
...

CallE fx es -> undefined
haskell functional-programming interpreter interpreted-language
2个回答
0
投票

大概CallE具有例程名称和参数列表,并且该例程以某种方式在环境中定义。因此,您将不得不在环境中查找名称以获取定义。您似乎没有为此的构造函数,因此您必须定义一个。大概像

Routine String [String]

第一个String是例程名称,第二个是形式参数名称列表。将形式参数名称和实际参数从CallE传递到envExtendMany以获取内部环境,然后使用该新环境调用interpExpr


0
投票

如果您说的是内置函数,则可能只需要打开函数名称即可。

CallE "sqr" [x] -> case interpExpr fenv env x of
                       ValueA (IntV v) -> ValueA (IntV (v ^ 2))
                       _ -> BadA
CallE "pow" [x,y] -> ...

这里有很多样板逻辑,我会将其分解为一个函数,以便您可以说:

CallE "sqr" [x] -> func1 (^2) x
CallE "sqrt" [x] -> func1 (floor . sqrt . fromIntegral) x
...

func1 :: (Integer -> Integer) -> Answer -> Answer
func1 f x = ... 

(以及类似的二进制函数)

© www.soinside.com 2019 - 2024. All rights reserved.