I am not exactly sure what I am doing wrong. I am stuck and I can't make anymore progress.
I put the error message I get in my code in comment.
If time allows, could someone please check my eval function? I think I am doing something terribly wrong.
Thank you.
Your Let handler will need to extend the environment with the new bindings, and then evaluate the expression with that new environment.
Your environment is a list of name, Value pairs, but the Let contains a list of name, Exp pairs, so you will need to convert the Exps into Values in order to extend the environment. Note that eval converts an Exp into a Value.
However, since the Let can hold multiple bindings, you will need to decide whether the Exps are evaluated in parallel, or sequentially (the difference between let and let* in lisp). Can a binding affect the value of following bindings? Depending upon the answer to that question, you will find yourself using either map or foldl to transform the list.
Your problem with the evaluation of Primitives is twofold. First, you are using a pattern which will only match against a list of exactly one element, but your primitives obviously take different numbers of arguments. The pattern should not use list syntax, since the Primitive constructor guarantees that there will be a list in that position. Instead, you should use a pattern that matches anything (like plain y). Second, the prim function is expecting a list of Values, but the Primitive constructor contains a list of Exp, so you will need to convert them (however, since evaluation of the arguments does not affect the environment, you will be using map).
To get you going in the right direction, in:
eval e (Primitive x [y]) = prim x [eval e y]
the [y] pattern will match only a single element list, with that element bound to y, and [eval e y] is going to result in a single element list. What you want is a pattern that matches the whole list, and then you want to transform that list by applying eval e to each element of that list.
The eval of If also has problems. The condition, the then, and the else are all of type Exp, but eval is supposed to return a Value, so you will have to transform something. Finally, the haskell if wants the condition to be a haskell Bool, but your condition is an Exp. You will need to evaluate the Exp into a Value, and then somehow extract a haskell Bool from the Value. Do you want Number and String Values to behave like Bools in your language (like python), or should only Bool Values behave like Bools?
Finally, finally, if you have any type errors (like trying to Add a String to a Number), or you supply the wrong number of arguments to a primitive, you are going to get a pattern match failure from the prim function (and possibly in the code you will have to write to extract a Bool from your If condition). That may or may not be what you want...
as Thomas M. DuBuisson already said, your let expression has invalid syntax. Second you really have to be aware what type of arguments function takes and what type it returns. You can not mix Exp with Value, for example - where Exp type is expected you have always pass value of Exp type etc.
eval :: Env -> Exp -> Value
-- the return type is Value
-- what are you trying to do here ? extract Value from x ...
eval e (Let [x] y) = eval e $ snd x
-- ... or from y ? Both x & y are of Exp type.
eval e (Let [x] y) = eval e y
There are also more type errors in your code:
eval e (Primitive x [y]) = prim x [y]
-- prim expects 2nd argument of [Value] type so it can be written as
eval e (Primitive x [y]) = prim x [eval e y]
-- dtto, mixing different types is wrong
eval e (If x y z) = if x then y else z
eval e (If x y z) = let Bool x' = eval e x in
if x' then (eval e y) else (eval e z)
and finally main expects IO () as the return type so you have to reflect this somehow, like printing the eval result:
print $ eval [("y", (Number 40))] (Let [("x", (Literal (Number 2)))] (Primitive Add [(Variable "x"), (Variable "y")]))
You want something like
let e' = {- extend env with x -} in eval e' y
Related
Here's the code.
largestDivisible :: (Integral a) => a
largestDivisible = head (filter p [100000,99999..])
where p x = x `mod` 3829 == 0
I am little bit confused. What is p in this case? Also, I do not understand the where expression in this particular example, because we got two expressions with p and x on the left side and we have one alignment, which is actually a boolean.
I would appreciate, if someone could explain me the above code.
p is a function, which accepts an argument x and returns True only if x is divisible by 3829. You can use where to define local functions just like you define local "values", using the same f x = y syntax you use to define top-level functions.
So I defined a 'match' function as follows
let match :: Eq a => a -> [a] -> [Int]; match x = map (fromEnum . (==x))
Now I'm trying to define a new 'countN' function that counts the matches. When I try
let countN :: a -> [a] -> Int; countN x xs = ? $ match x xs
I get errors of the form: 'parse error of input '?''
You're getting an error because the compiler is parsing ? as an operator, and it sees two operators in a row, the second being $, which is illegal syntax. It looks like you copy/pasted this from somewhere that had the ? there as something to fill in, what do you think goes there?
EDIT:
To elaborate, what would you make of an expression like
myFunc x = + * ++ / x
To humans and any Haskell compiler, this expression makes no sense. What do all of those operators mean there? It can't be composition, the types wouldn't line up, and there just aren't enough arguments. This is the sort of problem the compiler has when it sees ? $ match x xs.
This question already has answers here:
What does the : infix operator do in Haskell?
(4 answers)
Closed 8 years ago.
I've tried looking it up in hoogle and other various haskell dictionaries, but I can't find it. I was under the impression that it prepends, but I'm starting to see it in ways I haven't before and I've started second guessing myself.
For example, this is one of the questions that I don't understand:
(3 points) Fill in the blank with a pattern such that fun1 [(5,6),(7,8)] returns
5 and fun1 [(10,20),(30,40),(50,60)] returns 10:
and the answer is apparently:
((y,_):_)
fun1 _____________ = y
But I am so confused by this. I understand that the underscores mean that you don't really care about what the types of those are, but I don't understand what the (:) does in this answer.
While the other answers correctly explain what : is they don't quite answer the question - in the answer you have in your question : isn't used as a function, but as a constructor to pattern match on. fun (x:xs) = x means "if the argument is of the format (x:xs) give me the x". Pattern matching is used to "pull apart" complex types based on their constructors in Haskell.
In particular, since : is a list constructor you can pull apart lists with :
(conceptually list is defined as data [] a = [] | (:) a [a], although you're not gonna get this to compile because it's builtin syntax).
A non list example: We could define a datatype data F a b = A a | B b. This would create a type F that's parameterized with two types a and b and two constructors A and B with the types a -> F a b and b -> F a b respectively.
You could then write functions that use pattern matching to get at the contained values, like
isA (A _) = True -- this value was constructed with A, so it is an A
isA (B _) = False -- this value was constructed with B so it is not an A
or
getA (A a) = a -- this value was constructed with A so we can get an a out of it
getA (B _) = undefined -- ohps! We can't get an a back here cause we don't have one!
It is a List constructor function. It is used for prepending any value in front of the list.
ghci> 2 : [3,4]
[2,3,4]
It is just another Haskell function. You can also see it's type in ghci:
ghci> :t (:)
(:) :: a -> [a] -> [a]
Regarding your question, the answer is like this ((y,_):_) because it is being used in pattern matching. The first _ is the second element of the pair and the second _ pattern matches a list.
This may help you:
ghci> (5,6):[(7,8)]
[(5,6),(7,8)]
: is the list constructor of type a -> [a] -> [a]. It is usually used infix. but you can use it as prefix if you surround it with parentheses as you did. Just like any infix operation. (E.g. (+) 4 5 == 4 + 5)
So (:) a as is the same as a:as
Every constructor in Haskell can be also used do deconstruct a value of the type if constructs in a pattern match:
f x:xs = xs
would for example define a function that takes a non empty list and returns the tail. It would fail on an empty list because the empty list is constructed by the nullary constructor []. You could make f total by adding that second constructor to the match.
f [] = []
I guess your confusion comes from the fact that in haskell there is syntactic sugar that allows you to write lists in a more convenient way. Instead of (1:(2:(3:[]))) you can write [1,2,3] which is expanded into the former by the compiler.
In addition to the answers of what (:) function does, please, bear in mind that in the context of your question : is used as a deconstructor.
It is better to view (:) as a constructor. Then, just like any other data constructor, it can be used to introspect the contents of the value. Examples are:
f (Just x) = x -- extracts the value wrapped into Maybe a
f (x:_) = x -- extracts the value wrapped into a list, [a]
f ((x,_):_) = x -- extracts the value wrapped into a tuple in the list of tuples
In all these cases Just, : and (,) are constructors. The same syntax can be used to construct or deconstruct the values - depending on the context of the expression. Compare:
f x = Just x -- wraps x into Maybe a
f x xs = x:xs -- wraps x into a list, [a]
f x y z = (x,y):z -- wraps x into a tuple in the list of tuples
To understand what fun1 does, let's first look at another function:
f (x:xs) = x
If you pass this function a list such as [5,12,33], it will match x to 5, and xs to [12,33]. The function just returns x, i.e. the first element. So this function is basically the same as head. Since we don't actually use the value xs, we can rewrite the function as:
f (x:_) = x
Now let's look at fun1, but a slightly modified version.
fun1 ((y,z):xs) = y
If we pass this function the list [(5,6),(7,8)], it will match (y,z) to the pair (5,6) and xs to [(7,8)]. So now y is 5, and that's the value we return. Again, since we don't use z or xs, we can write the function as:
fun1 ((y,_):_) = y
i have this problem:
i want to have a list of strings representing math expression, and a map of arguments to replace the variables.
so if my list is like ["x","+","y","-","5"] and arguments are [("x","5"),("y","4")]
the function should return ["5","+","4","-","5"]
i have this function to find key from map (from the Learn you a haskell book)
findKey :: (Eq k) => k -> [(k,v)] -> Maybe v
findKey key [] = Nothing
findKey key ((k,v): xs) =
if key == k
then Just v
else findKey key xs
and then my function to replace the variables with values
takeValuesFromMap (x:str) m result
|x == [] = result
|findKey x m == Nothing = takeValuesFromMap str m (result++[x])
|otherwise = takeValuesFromMap str m result++[fromJust (findKey x m)]
if no match in the map, we pass the regular string. Otherwise we pass to the result the value staying next to the key that matches.
but in the end when i call
takeValuesFromMap ["x","+","y","-","5"] (Map.fromList [("x","5"),("y","4")]) []
it says
Solver.hs:63:48:
Couldn't match expected type `[([Char], [Char])]'
with actual type `Map.Map [Char] [Char]'
In the return type of a call of `Map.fromList'
In the second argument of `takeValuesFromMap', namely
`(Map.fromList [("x", "5"), ("y", "4")])'
In the expression:
takeValuesFromMap
["x", "+", "y", "-", ....]
(Map.fromList [("x", "5"), ("y", "4")])
[]
any idea how to fix this?
I'm going to take a different track here, and suggest that you don't solve this problem. The reason is that the list ["x","+","y","-","5"] is a very poor representation of the algebraic expression x + y - 5. I don't know exactly what you're trying to do, but a better approach would represent the expression as an abstract syntax tree, using an algebraic datatype.
So for example, we could use the following type to represent the expressions:
data Expr a = Variable String
| Literal a
| Plus Expr Expr
| Minus Expr Expr
Given this type, your example goes like this:
example :: Expr Integer
example = Minus (Plus (Var "x") (Var "y")) (Literal 5)
It's easy to write a function that evaluates expressions of this type, given a Map from variable names to values:
-- | Evaluate an expression, reading variable's values from the given environment
-- (the Map argument). Returns Nothing if any of the variables is undefined.
eval :: Num a => Expr a -> Map String a -> Maybe a
eval (Variable v) env = Map.lookup v env
eval (Literal x) _ = Just x
eval (Plus x y) env =
-- If this is confusing, read up on the Maybe monad in Learn You a Haskell
do x' <- eval x env
y' <- eval y env
return (x + y)
eval (Minus x y) env =
do x' <- eval x env
y' <- eval y env
return (x - y)
More complex, but well worth learning, is then to write a parser that takes a string and turns it into an Expr. If you're reading Learn You A Haskell, you may want to first get more comfortable with monads and applicatives. But when you're ready to take that step, there's a number of pages on the web with calculator parser examples:
http://meta-meta.blogspot.com/2007/10/simple-infix-calculator-in-haskell.html
http://www.youtube.com/playlist?list=PL_xuff3BkASMOzBr0hKVKLuSnU4UIinKx
http://haskelladdict.wordpress.com/2009/02/01/a-nice-little-calculator-implemented-in-haskell-and-parsec/
Though you may want to read this part of Real World Haskell first:
http://book.realworldhaskell.org/read/using-parsec.html
In findKey you require an association list, but you are actually using a Map. So, one way to fix it woulde be to remove Map.fromList.
Another point: Never replace pattern matching with equality checks! So please write:
| [] <- x = ...
| Nothing <- findKey x m = ...
Inspect the type of Map.fromList. Am I right in assuming that you take Map from Data.Map? If so:
:t Data.Map.fromList
Data.Map.fromList :: Ord k => [(k, a)] -> Map k a
So, this function returns Map, but your findKey actuall wants a list of tuples [([Char],[Char])]. You have got two choices now:
Use a function from Data.Map instead of your findKey to lookup a key.
Use another function to build your list.
I am reading a tutorial that uses the following example (that I'll generalize somewhat):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?
Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?
Seeing your edit, I think what your asking about is Pattern matching.
And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
However, there are more places where you can use pattern matching, other valid notations are:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.
Although these examples are specific to lists, you can do the same with other data types, like so:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
Again, the last function will also crash if you call it with Nothing.
To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.
Am I right about this behavior?
Yes. The names exist only in the block where you have defined them, though. In your case, this means the logical unit that your where clause is applied to, i.e. the expression inside fList.
Another way to look at it is that code like this
x where x = 3
is roughly equivalent to
let x = 3 in x
Yes, you're right. Names bound in a where clause are visible to the full declaration preceding the where clause. In your case those names are f and bar.
(One of the hard things about learning Haskell is that it is not just permitted but common to use variables in the source code in locations that precede the locations where those variables are defined.)
The place to read more about where clauses is in the Haskell 98 Report or in one of the many fine tutorials to be found at haskell.org.