I've recently picked up Haskell at uni and I'm working my way through a set of exercises, here's a snippet of one that I can't make sense of:
"Consider the following grammar for a simple, prefix calculator language:"
num ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
int ::= num | num int
expr ::= int | - expr | + expr expr | * expr expr
I'm confused as how to translate this into Haskell syntax (I'm a complete beginner in both Haskell and functional programming, please be gentle)
I suspect that num, int and expr are all, supposedly, types/values that can be declared using data or type and that they impose constraints on the calculator. However I can't make sense of either: How do I declare type or data(not a variable) for fixed values, namely 0-9? Also, how can I put symbols like - or + in a declaration?
Don't confuse a string in the grammar for the AST that represents it. Compare the string
"+ + 3 4 5"
which is a string in the grammar you've been given with
Plus (Plus (Literal 3) (Literal 4)) (Literal 5)
which would be a sensible Haskell value for the AST that String could get parsed to.
How do I declare type or data(not a variable) for fixed values, namely 0-9?
You can define a type, like
data Digit = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine deriving (Eq, Show)
This represents the num in your problem. Obviously we cannot use 0, 1, 2, 3, ... since they are already interpreted as numbers in Haskell.
Then, you can define
data Number = Single Digit | Many Digit Number deriving (Eq, Show)
which is equivalent to int in your problem. This type represents one (Single ...) or more (Many ...) digits, which together make a one decimal number. For example, with these data types a number 361 would be Many Three (Many Six (Single One)).
Also, how can I put symbols like - or + in a declaration?
There is no way to put those symbols in type or data declarations. You can use, however, names for the operations, like Sum, Sub and Mul. Then the expr of the grammar of your problem would translate to
data Expr = Lit Number
| Sub Expr Expr
| Sum Expr Expr
| Mul Expr Expr
deriving (Eq, Show)
If we would have a string "+ (- (2 5) (1 3)) 3", which represents an expression in the prefix calculator language of your problem , it would be parsed to Sum (Sub (Lit (Many Two (Single Five))) (Lit (Many One (Single Three)))) (Single Three).
If it is just a exercise about modeling data (without code) the answer consist of adding constructor names to your grammar (and changing literal number to names). Something like
data Num = Zero | One | Two | Three | Four | Five
| Six | Seven | Eight | Nine
data Int = Single Num | Multiple Num Int
data Exp = ExpInt Int | ExpMinus Exp Exp | ExpMul Exp Exp
| ExpMul Exp Exp
From that, you can write all sort of code, to parse and evaluate expressions.
Years ago, I got clever, and I declared my AST type an instance of Num, Eq and Ord, then defined the mathematical and comparison operators for AST expressions, so that expr1 + expr2 would yield a valid AST. Using sevenj’s declarations, this would be written like (+) x y = Sum x y, where the right-hand side is the constructor of an AST expression. For brevity, one = Lit One and two = Lit Two. Then you might write one + one == two and the operators would generate your AST with the correct precedence. Between that and abuse of the let { ... } in ... syntax to allow for arbitrary indentation, I had a way to write ASTs that was almost just the toy imperative language itself, with some boilerplate above, below and on the left.
The TA grading my assignment, though, was not amused, and wrote, “This is not Haskell!”
I'm taking a compilers class, and I decided to do it in haskell, but I'm having a hard time setting up the ast. My issue is that I have an Atom class and an Expr class and one instance of the Expr can be an Atom, but when the Expr is immediately an Atom it has an issue. Here is the example:
data Atom -- cannot be reduced farther
= Const Int -- int is value
| Var String -- string is name
deriving (Show) -- So we can print it
data Expr -- add input and the like
= Add Expr Expr -- add is two exprs
| USub Expr -- negation
| Input -- call to input
| Atomic Atom -- or an atomic
deriving (Show) -- So we can print it
data Statement
= Print Expr
| Discard Expr
| Assign String Expr
deriving (Show) -- So we can print it
main = do
let test5 = Print (Const 2)
putStrLn $ show test5
The compiler fails on the Print (Const 2) because it expected an Expr. Is there a fix to this, and is there better vocabular for expressing this problem?
Const 2 is an Atom, but Print takes an Expr as an argument. Luckily, every Atom can be made into an Expr with the Atomic constructor. So:
main = do
let test5 = Print (Atomic (Const 2))
print test5
First i want to say I'm a newbie in Haskell. Here's my problem:
For a school project I need to be able to parse and interprate and execute a fucntion call. This call needs to be able to execute a function already defined in haskell.
Parsing the call works, but i have no idea how to execute the function because the amount of arguments and type is unkown.
Here is how i represent my data
type Name = String
type Cond = Expr
data Expr
= Num Int
| Boolean Bool
| BinOp Op Expr Expr
| Var Name
deriving (Eq, Ord, Show)
data Stmnt
= Call Name [Expr]
| If Cond [Stmnt] [Stmnt]
| While Cond [Stmnt]
| VarDef Name Expr
deriving (Eq, Ord, Show)
This is a part of my interpeter. And it is with the implementation of funcall that I need help.
data Value = FineInt Int
| FineBool Bool
| FineFun ([Value] -> Value)
-- The enviroment keeps track of variables in the program
type Env = [(Name,Value)]
-- A state that takes an enviroment
type StEnv = State Env
evalstm :: Stmnt -> StEnv ()
evalstm (Call name exprs) = funcall name exprs
-- funcall name exprs = ?
I have the following data structures defined:
data Operator = Plus | Times | Minus deriving (Eq,Show)
data Variable = A | B | C deriving (Eq,Show)
newtype Const = D Numeral deriving (Eq,Show)
data CVO = Const | Variable | Operator deriving (Eq,Show)
type Expr = [CVO]
I have defined the following function:
eval2 :: Expr -> Integer
eval2 x = helper x
I would like to check if an element of the CVO list (Expr) is either an instance of Const, Variable or Operator (this works) and I would like to implement varying code for the specific type of the instance (e.g. Plus, Times, Minus for Operator).
helper :: Expr -> Integer
helper [] = 2
helper (x:xs)
| x == Operator && x == Plus = 1
I cannot compare x to Plus, because it expects x to be of type CVO.
Couldn't match expected type ‘CVO’ with actual type ‘Operator’
Is it somehow possible to cast x to be an instance of Operator in order to do the comparison?
A value can't have two different types at the same time. If x is a CVO you can't use == to compare it to Plus which is an Operator.
At the moment the type CVO consists of three constant values called Const, Variable and Operator. I'm guessing you actually wanted it to contain values of the type Const, Variable or Operator. You do that by declaring arguments to the constructors.
data CVO = Const Const -- a constructor whose name is Const and contains a value of type Const
| Var Variable -- a constructor named Var containing a Variable
| Op Operator -- a constructor named Op containing an Operator
A given value of type CVO must have been built from one of those three constructors, containing a value of the correct type. You can test which constructor was used to create the CVO, and simultaneously unpack the value, using pattern matching. Something like this:
helper :: Expr -> Integer
helper [] = 0
helper (Op o:xs) -- because we matched Op, we know o :: Operator
| o == Plus = 1
| otherwise = 2
helper _ = 3
In the process of writing an interpreter in Haskell for a separate, simple programming language - I find myself butting my head against a wall as I learn typing in Haskell.
I have two custom data types
data Expr
= Var Var
| NumE Int
| NilE
| ConsE Expr Expr
| Plus Expr Expr
| Minus Expr Expr
| Times Expr Expr
| Div Expr Expr
| Equal Expr Expr
| Less Expr Expr
| Greater Expr Expr
| Not Expr
| Isnum Expr
| And Expr Expr
| Or Expr Expr
| Head Expr
| Tail Expr
| Call String
deriving (Show, Read)
data Val = Num Int | Nil | Cons Val Val
deriving (Eq, Show, Read)
and I'm starting to write the cases for interpreting these options, with the function interpret_expr
interpret_expr :: Vars -> Expr -> Val
interpret_expr vars#(Vars a b c d) (NumE integer) = integer
but this COMPLAINS that it couldn't match expected type 'Val' with actual type 'Int' in the expression 'integer'. But say I change it to something silly like
interpret_expr :: Vars -> Expr -> Val
interpret_expr vars#(Vars a b c d) (NumE 'a') = 'a'
it then complains at 'a' that it can't match expected type 'Int' with actual type 'Char'. NOW IT WANTS AN INT?????? I really don't know what to say, I really thought it would be as simple as providing NumE with a variable it could figure is an integer. What am I doing wrong?
In the first case you are returning an Int from a function you declared to return a Val. From your definition of Val it looks like you probably want to return Num integer here.
In the second case the problem is in the pattern matching. (NumE 'a') is an error because NumE is defined as NumE Int, so it must be followed by an Int, not a Char.