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.
Related
deadNeighbors:
Give a list of empty cells that have a living cellular neighbor in that generation. Make sure that each cell is listed only once!
Something not work with my deadNeighbors function, but I do not know what is wrong about it. Can anybody help me to fix deadNeighbors ?
type Coordinate = (Integer, Integer)
type Generation = [Coordinate]
single :: Generation
single = [ (42, 42) ]
row :: Generation
row = [ (10, 1), (10, 2), (10, 3) ]
Code:
neighbors :: Coordinate -> [Coordinate]
neighbors (x,y) = [(x-1,y-1), (x-1,y), (x-1,y+1), (x ,y-1), (x,y+1), (x+1,y-1), (x+1,y), (x+1,y+1)]
alive :: Generation -> Coordinate -> Bool
alive x y = elem y x
livingNeighbors :: Generation -> Coordinate -> Int
livingNeighbors a = length .filter (alive a) . neighbors
staysAlive :: Generation -> Coordinate -> Bool
staysAlive a b
| alive a b = livingNeighbors a b `elem` [2,3]
| otherwise = livingNeighbors a b `elem` [3]
Problems:
deadNeighbors :: Generation -> [Coordinate]
deadNeighbors (neighbors (x,y))
|(alive (x,y)) = Nothing
|otherwise = [] ++ (x,y)
Examples:
sort (deadNeighbors single) == sort [(41.41), (41.42), (41.43), (42.41), (42.43), (43.41), (43.42) , (43.43)]
sort (deadNeighbors row) == sort [(9.0), (9.1), (9.2), (10.0), (11.0), (11.1), (11.2) , (9.3), (11.3), (9.4), (10.4), (11.4)]
Let's go over deadNeighbors function line by line:
(the type signature looks fine)
deadNeighbors (neighbors (x,y))
This is a clause of the deadNeighbors function and seems to use pattern matching notation, however you use the function neighbors in the pattern match. That is not allowed. I don't really know what your intention is here, so I cannot suggest a way to fix this.
|(alive (x,y)) = Nothing
Here you are using a guard correctly, but the alive function requires the generation in addition to the coordinate. You should pass both as arguments here.
Also, you are returning Nothing which has type Maybe a for some a. But the signature of the deadNeighbors function indicates it should return a [Coordinate]. Perhaps you intended to write [] (the empty list)?
|otherwise = [] ++ (x,y)
Here you are using the ++ operator, which expects two lists as arguments, with an empty list [] as argument and a coordinate (x,y). The coordinate type is not a list, so it is not compatible with the ++ operator. Perhaps you intended (x,y) : [] or just [(x,y)] (which means the same thing but is slightly prettier)?
I have an assigment where I have to program an evaluation function eval::Ast -> String which evaluates any Ast into a string. for example:
>eval (parse "hel + lo")
"hello"
> eval (parse "mi + 2 * la")
"milala"
I've made a parse-function that e.g. takes "hel + lo" and returns Plus (Word "hel") (Word "lo")
But I am very unsure of what the function (and types) should look like as there are multiple types involved in the evaluation of the AST... Anyone who can put me in the right direction?
The AST is defined as
data Ast
= Word String
| Num Int
| Mult Ast Ast
| Plus Ast Ast
| Minus Ast Ast
deriving (Eq, Show)
eval :: AST -> String is what defines the semantics of your operations. For example, eval (Plus (Word x) (Word y)) == x ++ y.
However, what should eval (Plus x y) produce if both arguments are numbers? Should it concatenate them, or add them numerically? What if either one itself is one of the Plus, Minus, or Mul values? You would need to evaluate them first, but then you can't tell if a result like "2" is really a string, or the result of a number.
You also need to decide if every AST can be evaluated: does Mul (Word "x") (Word "y") make sense? If not, what String would you return?
I would suggest two things:
First, define a simplify function that takes care of reducing the AST to something simpler. It will take care of doing things like numerical arithmetic in the case of Plus (Num ...) (Num ...), but leave things like Word x or Plus (Word x) (Num y) unchanged.
simplify :: AST -> AST
simplify (Num x) = Num x -- Easy case done for you; no simplification necessary
simplify (Word x) = ...
-- Hint: in each of the following, you need to recursively simplify the operands.
-- Once you do that, you can either simplify further, or return a new
-- node to be evaluated.
simplify (Plus x y) = ...
simplify (Minus x y) = ...
simplify (Mul x y) = ...
Second, define eval :: AST -> Either String String, will first use simplify on its argument, then do case-by-case conversions of ASTs to Strings where feasible, and returning an appropriate error message where it isn't.
eval :: AST -> Either String String
eval x = eval' (simplify x)
where eval' (Word x) = Right x -- Easy case done for you
eval' (Num x) = ...
-- simplify will have reduced all the Num + Num, Num - Num, and
-- Num * Num nodes to single Num nodes already.
eval' (Plus (Word x) (Word y)) = x ++ y -- Other easy case done above
eval' (Plus x y) = ...
eval' (Minus (Word x) (Word y)) = ...
eval' (Minus x y) = ...
eval' (Mul (Word x) (Word y)) = ...
eval' (Mul x y) = ...
Note that you could conceivably define some combinations in either eval' or simplify, e.g.
simplify (Plus (Word x) (Word y)) == Word $ x ++ y
leaving the more complicated (and possibly impossible) cases to eval.
Recently I am trying to figure out how to do some programming in Haskell.
I'm trying to do some simple operations. Right now I'm stuck with an operation like in this example:
input = [1,2,3,4]
output = [1,2,2,3,3,3,4,4,4,4]
That is, for each element x in input, produce x elements of x in output. So, for element 1 in input, append [1] to output. Then, for element 2 in input, append elements [2,2] to output. Then, for element 3, append [3,3,3], etc. The algorithm should work only on standard numbers.
I know it's very easy, and it's trivial to perform it in "normal" imperative programming, but as Haskell's functions are stateless, I'm having a problem in how to approach this.
Could anyone please give me some hint how can an absolute Haskell beginner cope with this?
You've just discovered monads!
Here's the general idea of what you're doing:
For each a-element in the input (which is a container-type M a, here [a]), you specify an entire new container M b. But as a final result, you want just a single "flat" container M b.
Well, let's take a look at the definition of the Monad type class:
class (Applicative m) => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
which is exactly what you need. And lists are an instance of Monad, so you can write
replicates :: [Int] -> [Int]
replicates l = l >>= \n -> replicate n n
Alternatively, this can be written
replicates l = do
n <- l
replicate n n
It might be interesting to know that the, perhaps easier to understand, list comprehension
replicates l = [ n | n <- l, _ <- [1..n] ]
as suggested by chi, is actually just syntactic sugar for another monad expression:
[ n | n <- l, _ <- [1..n] ] ≡ l >>= \n -> [1..n] >>= \_ -> return n
... or least it used to be in some old version of GHC, I think it now uses a more optimised implementation of list comprehensions. You can still turn on that de-sugaring variant with the -XMonadComprehensions flag.
Yet another solution, exploiting list comprehensions:
output = [ n | n <- input , m <- [1..n] ]
Compare the above with the imperative Python code:
for n in input: -- n <- input
for m in range(1,n+1): -- m <- [1..n] (in Python the second extreme is excluded, hence +1)
print n -- the n in [ n | ... ]
Note that m is unused -- in Haskell it is customary to can call it _ to express this:
output = [ n | n <- input , _ <- [1..n] ]
As a beginner, I more easily understand something like this:
concat $ map (\x -> take x $ repeat x) [1,2,3,4]
For "list as monads" it is important to know that there is also "concat" operation under the hood (in bind definition), IMO
A simple solution:
rep (x:xs) = replicate x x ++ rep xs
rep [] = []
Hints:
replicate 5 "a" gives ["a","a","a","a","a"], and it works the same way for any type in the second argument, but first argument must be of type Int
the operator ++ concatenates two lists
so the inferred type of rep is [Int] -> [Int], if you need to use other types you should use conversion functions
Again I am stuck.
I have a list of pairs of strings [(String, String)] and want to look for another String in it.
When the substring matches the first in the tuple, I'd like to return the second one and vice versa.
I had some ideas but again, I don't know how to correctly apply functions in Haskell.
My first idea was to use map but that wouldn't really be able to give me a String as a result, would it?
I was thinking about using filter. First searching the substring in the first of the pair and then in the second ones.
This is as far as I got:
search :: String -> [(String, String)] -> String
search substr xs = filter(==substr) xs.fst
And it doesn't even work :/
I'd be thankful for any kind of advice!
Thanks
I would suggest you to wrap the return type in Maybe in case the substring isn't found.
search :: Eq a => a -> [(a, a)] -> Maybe a
search s xs = case lookup s xs of
Just x -> Just x
Nothing -> lookup s xs'
where xs' = map swap xs
If you don't want to wrap it with Maybe, just use the fromJust function and change the type signature accordingly. In the above code, you are using the library defined lookup function. And in case the lookup fails in the first search you exchange the tuples and again perform the lookup operation. Also, Don't forget to import swap from Data.Tuple.
Demo in ghci:
ghci > let a = [("hi","bye"),("cat", "dog")]
ghci > search "hi" a
Just "bye"
ghci > search "dog" a
Just "cat"
You can call lookup on the list, and then call lookup after swapping each tuple in the list. But this means possibly traversing the list twice.
lookup' k = foldl acc Nothing
where
acc (Just x) _ = Just x
acc _ (a,b) | k == b = Just a | k == a = Just b | otherwise = Nothing
This way you traverse the list only once. This version doesn't terminate on infinite lists if the element is present. You can write it using foldr, but that for that version, lookup' 0 [(0,1), undefined] == undefined as opposed to the preferred behavior.
You can also write it using explicit recursion. For once, using explicit recursion is better! It covers both of the cases covered above:
lookup'' k [] = Nothing
lookup'' k ((a,b):xs)
| k == a = Just b
| k == b = Just a
| otherwise = lookup'' k xs
>lookup'' 1 [(1,0), undefined]
Just 0
>lookup'' 1 (zip [0..] [0..])
Just 1
user2407038's solution, lookup'' is the most efficient since it traverses the list only once, and terminates early when a match is found. It can be written without explicit recursion as follows:
import Control.Monad ( msum )
lookup'' k = msum . map match
where match (a, b) | k == a = Just b
| k == b = Just a
| otherwise = Nothing
I'm trying to understand how Haskell list comprehensions work "under the hood" in regards to pattern matching. The following ghci output illustrates my point:
Prelude> let myList = [Just 1, Just 2, Nothing, Just 3]
Prelude> let xs = [x | Just x <- myList]
Prelude> xs
[1,2,3]
Prelude>
As you can see, it is able to skip the "Nothing" and select only the "Just" values. I understand that List is a monad, defined as (source from Real World Haskell, ch. 14):
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
xs >> f = concat (map (\_ -> f) xs)
fail _ = []
Therefore, a list comprehension basically builds a singleton list for every element selected in the list comprehension and concatenates them. If a pattern match fails at some step, the result of the "fail" function is used instead. In other words, the "Just x" pattern doesn't match so [] is used as a placeholder until 'concat' is called. That explains why the "Nothing" appears to be skipped.
What I don't understand is, how does Haskell know to call the "fail" function? Is it "compiler magic", or functionality that you can write yourself in Haskell? Is it possible to write the following "select" function to work the same way as a list comprehension?
select :: (a -> b) -> [a] -> [b]
select (Just x -> x) myList -- how to prevent the lambda from raising an error?
[1,2,3]
While implemenatations of Haskell might not do it directly like this internally, it is helpful to think about it this way :)
[x | Just x <- myList]
... becomes:
do
Just x <- myList
return x
... which is:
myList >>= \(Just x) -> return x
As to your question:
What I don't understand is, how does Haskell know to call the "fail" function?
In do-notation, if a pattern binding fails (i.e. the Just x), then the fail method is called. For the above example, it would look something like this:
myList >>= \temp -> case temp of
(Just x) -> return x
_ -> fail "..."
So, every time you have a pattern-match in a monadic context that may fail, Haskell inserts a call to fail. Try it out with IO:
main = do
(1,x) <- return (0,2)
print x -- x would be 2, but the pattern match fails
The rule for desugaring a list comprehension requires an expression of the form [ e | p <- l ] (where e is an expression, p a pattern, and l a list expression) behave like
let ok p = [e]
ok _ = []
in concatMap ok l
Previous versions of Haskell had monad comprehensions, which were removed from the language because they were hard to read and redundant with the do-notation. (List comprehensions are redundant, too, but they aren't so hard to read.) I think desugaring [ e | p <- l ] as a monad (or, to be precise, as a monad with zero) would yield something like
let ok p = return e
ok _ = mzero
in l >>= ok
where mzero is from the MonadPlus class. This is very close to
do { p <- l; return e }
which desugars to
let ok p = return e
ok _ = fail "..."
in l >>= ok
When we take the List Monad, we have
return e = [e]
mzero = fail _ = []
(>>=) = flip concatMap
I.e., the 3 approaches (list comprehensions, monad comprehensions, do expressions) are equivalent for lists.
I don't think the list comprehension syntax has much to do with the fact that List ([]), or Maybe for that matter, happens to be an instance of the Monad type class.
List comprehensions are indeed compiler magic or syntax sugar, but that's possible because the compiler knows the structure of the [] data type.
Here's what the list comprehension is compiled to: (Well, I think, I didn't actually check it against the GHC)
xs = let f = \xs -> case xs of
Just x -> [x]
_ -> []
in concatMap f myList
As you can see, the compiler doesn't have to call the fail function, it can simply inline a empty list, because it knows what a list is.
Interestingly, this fact that the list comprehensions syntax 'skips' pattern match failures is used in some libraries to do generic programming. See the example in the Uniplate library.
Edit: Oh, and to answer your question, you can't call your select function with the lambda you gave it. It will indeed fail on a pattern match failure if you call it with an Nothing value.
You could pass it the f function from the code above, but than select would have the type:
select :: (a -> [b]) -> [a] -> [b]
which is perfectly fine, you can use the concatMap function internally :-)
Also, that new select now has the type of the monadic bind operator for lists (with its arguments flipped):
(>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = concatMap f xs -- 'or as you said: concat (map f xs)