As part of defining a language interpreter I have the following definition:
initCtx :: Context
initCtx = (Map.empty, initEnv)
where initEnv =
Map.fromList [ ...
, ("+", undefined)
...
]
And for the sum operation I have this:
evalExpr :: Expr -> Interpreter Value
evalExpr (e1 :+: e2) = do v1 <- eval e1
v2 <- eval e2
return Interpreter $ (v1 + v2)
The exalExpr is made by me, but what do I need to write in place of undefined so that the expression is executed? Or, perhaps, I am looking to the wrong thing ? I have more operations of course, but I just need to have an example. I am veeeeery new to Haskell, I am practically required to deal with it.
Thanks!
EDIT:
type Env = Map Ident Value
type Primitive = [Value] -> Interpreter Value
type PEnv = Map FunName Primitive
type Context = (Env, PEnv)
Here's Expr:
data Expr = Number Int
| String String
| Array [Expr]
| Undefined
| TrueConst
| FalseConst
| Var Ident
| Compr ArrayFor Expr
| Call FunName [Expr]
| Assign Ident Expr
| Comma Expr Expr
deriving (Eq, Read, Show)
And Interpreter
newtype Interpreter a = Interpreter {runInterpreter :: Context -> Either Error (a, Env)}
And Value:
data Value = IntVal Int
| UndefinedVal
| TrueVal | FalseVal
| StringVal String
| ArrayVal [Value]
deriving (Eq, Show)
Alright, I'll take a stab at this...
So it looks like a Context consists of a pair of maps. It appears the first map lets you look up a variable's value from its name. The second one lets you look up a function name and get the corresponding executable code for it.
You're using Interpreter as if it's a monad; I don't know whether it actually is, but it looks plausible.
So initCtx starts off with no variables defined (Map.empty), and presumably you're meant to put a bunch of predefined functions like + in the second map.
Looking at the definition for Primitive, it takes a list of Value and returns an Interpreter computation. So I guess it looks something like
addExpr :: [Value] -> Interpreter Value
addExpr [e1, e2] = do
v1 <- eval e1
v2 <- eval e2
return (v1 + v2)
and then you could write map.fromList [... ("+", addExpr) ...].
Except that's not quite right either. Value isn't a number type; what happens if, say, v1 = StringVal? For that matter, what if somebody calls "+" with a different number of arguments? We need some error checking here.
I'm guessing the thing you're looking for probably looks something like this:
checkInt :: Value -> Interpreter Int
checkInt (IntVal x) = return x
checkInt _ = Interpreter $ ctx -> Left "Not an integer."
addExpr :: [Value] -> Interpreter Value
addExpr [expr1, expr2] do
val1 <- eval expr1
int1 <- checkInt val1
val2 <- eval expr2
int2 <- checkInt val2
return (IntVal $ int1 + int2)
addExpr _ = Interpreter $ ctx -> error "Wrong number of arguments."
Related
I'm trying to write an evaluation function for a language that I am working on in which non-determinism can be permitted within an if-block, called a selection block. What I'm trying to achieve is the ability to pick an if/selection statement from the block whose guard is true and evaluate it but it doesn't matter which one I pick.
From searching, I found an example that performs in a similar way to what I would like to achieve through modelling coinflips. Below is my adapation of it but I'm having issue in applying this logic to my problem.
import Control.Monad
data BranchType = Valid | Invalid deriving (Show)
data Branch = If (Bool, Integer) deriving (Show, Eq)
f Valid = [If (True, 1)]
f Invalid = [If (False, 0)]
pick = [Invalid, Invalid, Valid, Invalid, Valid]
experiment = do
b <- pick
r <- f b
guard $ fstB r
return r
s = take 1 experiment
fstB :: Branch -> Bool
fstB (If (cond, int)) = cond
main :: IO ()
main = putStrLn $ show $ s -- shows first branch which could be taken.
Below is my ADT and what I have been trying to make work:
data HStatement
= Eval HVal
| Print HVal
| Skip String
| Do HVal [HStatement]
| If (HVal, [HStatement])
| IfBlock [HStatement] -- made up of many If
| Select [HStatement] -- made up of many If
deriving (Eq, Read)
fstIf :: HStatement -> Bool
fstIf (If (cond, body)) = if hval2bool cond == True
then True
else False
h :: Env -> HStatement -> IOThrowsError ()
h env sb = do
x <- g env sb
guard $ fstIf x -- Couldn't match expected type ‘HStatement’ with actual type ‘[HStatement]’
-- after guard, take 1 x then evaluate
g :: Env -> HStatement -> IOThrowsError [HStatement]
g env (Select sb) = mapM (\x -> f env x) sb
f :: Env -> HStatement -> IOThrowsError HStatement
f env (If (cond, body)) = evalHVal env cond >>= \x -> case x of
Bool True -> return $ If (Bool True, body)
Bool False -> return $ If (Bool False, body)
The error I receive is the following : Couldn't match expected type ‘HStatement’ with actual type ‘[HStatement]’ at the guard line. I believe the reason as to why the first section of code was successful was because the values were being drawn from List but in the second case although they're being drawn from a list, they're being drawn from a [HStatement], not something that just represents a list...if that makes any sort of sense, I feel like I'm missing the vocabulary.
In essence then what should occur is given a selection block of n statement, a subset of these are produced whose guards are true and only one statement is taken from it.
The error message is pretty clear now that you have some types written down. g returns IOThrowsError [HStatement], so when you bind its result to x in h, you have an [HStatement]. You then call fstIf, which expects a single HStatement, not a list. You need to decide how to handle the multiple results from g.
I'm learning Haskell, and it's not always clear to me when to use a matcher and when to use a guard. For certain scenarios it seems that matchers and guards can be used to achieve essentially the same ends. Are there some rules or heuristics for when it's better to use matches over guards or vice versa? Is one more performant than the other?
To illustrate what I'm getting at, here are a couple of silly examples I cooked up that seem to be equivalent, but one version uses matchers and the other uses guards:
listcheck :: [a] -> String
listcheck [] = "List is null :-("
listcheck a = "List is NOT null!!"
listcheck' a
| null a = "List is null :-("
| otherwise = "List is NOT null!!"
and
luckyseven :: Int -> String
luckyseven 7 = "SO LUCKY!"
luckyseven b = "Not so lucky :-/"
luckyseven' c
| c == 7 = "SO LUCKY!"
luckyseven' c = "Not so lucky :-/"
Thanks!
These can often be used interchangeably, but there are significant differences between the two. Pattern matching can only occur on constructors, so computations can not be performed inside of a pattern, while guards are simply multi-branch if-else statements. For example, I can't write a pattern equivalent of the following:
func :: Int -> Int
func x
| even x = 3 * x
| odd x = 7 * x -- alternatively "otherwise = 7 * x" to get rid of all those pesky compiler warnings
This just wouldn't be possible with just pattern matching. You also can't do things like
func :: Int -> Maybe String
func x
| x < 0 = Nothing
| x == 0 = Just "Zero"
| x < 20 = Just "Small"
| x < 100 = Just "Big"
| x < 1000 = Just "Huge"
| otherwise = Just "How did you count that high?"
Conversely, guards using ADTs don't give you much information without helper functions. If I had the type
data Expr
= Literal Int
| Add Expr Expr
| Mult Expr Expr
| Negate Expr
deriving (Eq, Show)
Using guards to write the equivalent of
eval :: Expr -> Int
eval (Literal i) = i
eval (Add e1 e2) = eval e1 + eval e2
eval (Mult e1 e2) = eval e1 * eval e2
eval (Negate e) = negate (eval e)
would be a lot more verbose, difficult, and annoying. In fact, at some level you'd have to resort to pattern matching to do things like
getLiteral :: Expr -> Int
getLiteral (Literal i) = i
getLiteral _ = error "Not a literal"
Which introduces functions that can error, which is bad. In this case, using pattern matching is much preferred over using guards.
For your particular examples, I'd go with pattern matching, but would use _ where possible:
listCheck :: [a] -> String
listCheck [] = "List is null :-("
listCheck _ = "List is NOT null!!"
and
luckySeven :: Int -> String
luckySeven 7 = "SO LUCKY!"
luckySeven _ = "Not so lucky :-/"
That emphasizes that if the list isn't empty, or the Int isn't 7, nothing else matters, and you aren't going to use its particular value to produce the function result. bheklilr has capably pointed out places where one choice or the other is definitely preferable.
I'm trying to create a compiler into an intermediate language, and for that purpose I created the following data types:
data C = Atr Var Var
deriving(Show)
data E = Var Op Var
deriving (Show)
data Var = V String
| N Int
deriving (Show)
data Op = OpPlus
| OpMinus
| OpMult
| OpDiv
deriving (Show)
But I'm having problems when I use the E data type, for example:
compileE :: Exp -> Int -> [(String,Int)] ->(Int,Var,[C])
compileE ( Plus e1 e2 ) k regs = let (v1,t1,l1)= (compileE e1 k regs);
( v2,t2,l2 ) =( compileE e2 v1 regs);
t = new_Var v2
in (v2+1,V t, l1 ++ l2 ++ [Atr (V t) (t1 OpPlus t2)])
In the expression "t1 OpPlus t2", it says t1 is applied to too many arguments. That would make sense since t1 doesn't exist in the data type, but t1 is a Var and that expression should be in the Var Op Var form.
Any sugestions on a work around?
EDIT:
Aparently my english sucked and i didn't explain well my question:
My intermediate language needs to be defined using this rule, among others: "E<- Var Op Var" where E is an expression, Var could be an int or string (case of variable) and Op the symbol im using. At the end of the compileE function, im trying to concatenate the previous expressions ( l1 and l2) with the current one to create the [C] list.
My problem is that I'm not being able to add the "Var Op Var" format (t1 OpPlus t2) because its listing t1 as a function and not as part of the Var data type.
It looks like you forgot to give E a data constructor of its own. data E = Var Op Var defines Var as the data constructor for E, and it takes two arguments (one Op, one Var). Because Var is also the name of a separate type, this is not a good idea. It seems that you meant to write E = E' Var Op Var, where E' is some new name (it could even be E!), after which (assuming I'm reading your intent correctly) t1 OpPlus t2 becomes E' t1 OpPlus t2.
Note that, even after you fix this, your code still won't work, as it looks like you're trying to use an E value as the second argument to Atr, even though the second argument should be a Var. What are you really trying to do there?
data Exp = Plus Exp Exp
| Name String
| Const Int
data C = Atr Var E
deriving(Show)
data E = E Var Op Var
deriving (Show)
data Var = V String
| N Int
deriving (Show)
data Op = OpPlus
| OpMinus
| OpMult
| OpDiv
deriving (Show)
new_Var :: Int -> String
new_Var i = "sym" ++ show i
compileE :: Exp -> Int -> [(String,Int)] ->(Int,Var,[C])
compileE (Name s) k regs = (k, V s, [])
compileE (Const i) k regs = (k, N i, [])
compileE (Plus e1 e2) k regs = (v2+1, V t, l1 ++ l2 ++ [Atr (V t) (E t1 OpPlus t2)])
where (v1,t1,l1) = compileE e1 k regs
(v2,t2,l2) = compileE e2 v1 regs
t = new_Var v2
The above passes compilation. I made up an Exp type to match more or less what I thought would be the AST compileE is expecting. The end result corresponds to the signature of your function. new_Var generates symbols for your variables. At this point you probably don't need yet the regs variable; it will probably be useful at a later stage, when your compiler does the register allocation phase.
I have 2 lists Expressions and bindings (id = Expr), and trying to replace each expression with its equivalent from the bindings list in a new list called newE, where Expression = id ..
Initially, I have only one expression:
eq (div (add 2 7) (sub 5 2)) 3
I want to replace each identifier in this expression with its equivalent from the bindings list, so I tried to split this expression into a list of strings and removed brackets, to separate each identifier ..
This is how I tried to implement it:
newE = [\x -> getExp(b) | x <- eStr, b <- bs, x == getId(b)]
where es = getExpressions (prog)
bs = getBindings (prog)
-- Extracting expression into a list of strings
-- and removing brackets
eStr = map (delete ')')(map (delete ')')
(map (delete '(') (split " " (show es))))
newE' = join " " newE
Is this correct?
Now I'm getting errors that newE returns [t0 -> Expr] while it's supposed to return Expr only, why is that?
and the join function is expecting a [Char] .. while its type in the Data.List.Utils documentation is:
join :: [a] -> [[a]] -> [a]
so, isn't it supposed to accept any type not just list of characters? or did it get confused with a 'join' from another library?
I searched the libraries I've imported, but they don't have a join.
Any help to resolve these errors and modify the code to do what it's supposed to do?
Thank you
Since you asked, here is a sketch of the conventional approach:
Convert the string expression into a Expr value, e.g.
add 2 7 -> App (App (Var "add") (Var "2")) (Var "7")
Write a function lookupBinding to lookup a binding for a Symbol:
lookupBinding :: [Binding] -> Symbol -> Maybe Expr
Write a substitute function to substitute binding definitions into an expression:
substitute :: [Binding] -> Expr -> Expr
It will go something like this:
substitute bindings (App e1 e2) = App e1' e2'
where e1' = substitute bindings e1
e2' = substitute bindings e2
substitute bindings (Var sym) = ... lookupBinding sym ...
substitute bindings (Lam sym exp) = ... substitute bindings' exp ...
Your list comprehension body returns the function \x -> getExp b. That's why the compiler says it's returning a function type.
Reading through Why It’s Nice to be Quoted, in section 3 there's an example of splicing a variable identifier in a quasiquote.
subst [:lam | $exp:e1 $exp:e2 |] x y =
let e1' = subst e1 x y
e2' = subst e2 x y
in
[:lam | $exp:e1' $exp:e2' |]
I see why the recursive calls to subst are done outside the [:lam| ... |], it's because the function antiVarE in section 3.2 builds a TH.varE out of the variable name.
My question is how much work would be required to support arbitrary expression splices beyond just a variable name?
For example:
subst [:lam | $exp:e1 $exp:e2 |] x y =
[:lam | $exp:(subst e1 x y) $exp:(subst e2 x y) |]
Answering my own question for posterity.
Turns out it was quite simple. Using the parseExp function in haskell-src-meta package I was able to easily convert a string to AST fragment.
In the original paper, aside from the parser changes required to capture an expression string between parentheses, the antiExpE function could be rewritten as such.
antiExpE :: Exp -> Maybe TH.ExpQ
antiExpE (AE v) =
case parseExp v of
Right exp -> Just . return $ exp
Left _ -> Nothing
antiExpE = Nothing