I am learning Haskell, and I encounter a tricky problem which is evaluating String containing a simple arithmetic expression like (+) and (-) to int.
Take some for example:
"1+2+3" -> 6 , " " -> 0 .
I am trying to type the code. However, I cannot complete that. The following is my code.
evalExpr xs = foldl f 0 xs where
f acc x | x == "+" = (+) acc
| x == "-" = (-) acc
| x == " " = 0
| otherwise = read x ::Int
* In the expression: read x :: Int
In an equation for `f':
f acc x
| x == "+" = (+) acc
| x == "-" = (-) acc
| x == " " = 0
| otherwise = read x :: Int
In an equation for `evalExpr':
evalExpr xs
= foldl f 0 xs
where
f acc x
| x == "+" = (+) acc
| x == "-" = (-) acc
| x == " " = 0
| otherwise = read x :: Int
* Relevant bindings include
acc :: a1 (bound at A2.hs:24:8)
f :: a1 -> [Char] -> a1 -> a1 (bound at A2.hs:24:6)
Could someone help me? Thank you!
Your issue is that the result type of f is different in different branches, which is not allowed. In the first two it is (e.g.) Int -> Int, the type of (+) 3 (which is the same as \x -> 3 + x. The type of the third and fourth lines is just Int. These types are not the same.
Here is a simple solution.
data Token = Plus | Minus | Num Int
lex [] = Nothing
lex ('+':s) = Just (Plus,s)
lex ('-':s) = Just (Minus,s)
lex (num:s) | isDigit num = Just (Num k,rest) where
numstr a (d:s) | isDigit d = numstr (digitVal d:a) s
numstr a r = a,r
digits,rest = numstr [digitVal num] s
k = foldr 0 (\acc d -> acc*10 + d) digits
parse s = case lex s of
Nothing -> []
Just (x,s') -> x:parse s'
eval (Num n:r) = eval (Plus:Num n:r)
eval = eval' 0 where
eval' acc (Plus:Num n:r) = eval' (acc+n) r
eval' acc (Minus:Num n:r) = eval' (acc-n) r
Related
I want to write a program to find the first few rows of the Pascal Triangle.
This is the work I've done so far:
-- Gets the next row given the previous row
cur_row :: [Integer] -> [Integer]
cur_row x = ans where
ans = zipWith (\a b -> a + b) (0 : x) (x : 0)
-- Gets the xth row
rows_helper :: Int -> [Integer]
rows_helper x
| x == 1 = [1]
| otherwise = cur_row (rows_helper (x - 1))
-- Main Function : Finds the first x rows of the Pascal's Triangle
rows :: Int -> [[Integer]]
rows x
| x == 0 = []
| x == 1 = [[1]]
| otherwise = rows (x - 1) ++ [rows_helper(x)]
rows is the actual function that should return x rows of the Pascal Triangle.
rows_helper is meant to find the xth row of the Pascal Triangle.
To implement rows_helper, I need to implement cur_row which, from the previous row, returns the current row.
But, when I run it, I get
Couldn't match type ‘[Integer]’ with ‘Integer’
Expected type: [Integer]
Actual type: [[Integer]]
• In the third argument of ‘zipWith’, namely ‘(x : 0)’
In the expression: zipWith (\ a b -> a + b) (0 : x) (x : 0)
In an equation for ‘ans’:
ans = zipWith (\ a b -> a + b) (0 : x) (x : 0)
|
5 | ans = zipWith ( b -> a + b) (0 : x) (x : 0)
| ^^^^^
I don't understand why I'm getting this. Can someone help?
Thanks
please pardon for very beginner level quesion.
I am now trying to introduce Maybe into my previous helper function (which swaps the first two elements of the list) to enable empty list error handling:
...haskell
-- | the helper funtion to only swap the first two elements.
swap_first_two_elements :: [a] -> Maybe [a]
swap_first_two_elements list = case list of
x:y:xs -> Just (y:x:xs)
_ -> Nothing
and invoking it in
interprete s x
| x `elem` ["+","-","*","/","^"] = operate x s
| x `elem` ["inc","dec","sqrt","sin","cos","inv"] = operate2 x s
| x `elem` ["+all"] = [sum s]
| x `elem` ["dup"] = (head s) :s
| x `elem` ["pop"] = tail s
| x `elem` ["swap"] = swap_first_two_elements s
| x `elem` ["clear"] = drop (length s) s
| x `elem` ["*all"] = [product s]
| otherwise = read x:s
where
operate op (x:y:s) = case op of
"+" -> x + y:s
"-" -> y - x:s
"*" -> x * y:s
"/" -> y / x:s
"^" -> y ** x:s
But I am getting an error like
Couldn't match expected type [a] with actual type Maybe[a]
I read other related posts and modified it like:
| x `elem` ["swap"] = swap_first_two_elements Just(s)
Still got error. Could experts offer where I go wrong? Thank you.
So you have
interprete s x
| x `elem` ["pop"] = tail s
| x `elem` ["swap"] = swap_first_two_elements s
Now,
tail :: [a] -> [a]
but
swap_first_two_elements :: [a] -> Maybe [a]
and of course those are two different types altogether.
You can't return a value of one type in some case, and of another type altogether in some other cases. All cases in a function definition must return values of the same type.
A function goes from a type to a type, not to types.
You can fix your definition by wrapping all the other cases' values in a Just, like so:
| x `elem` ["pop"] = Just (tail s)
Just for your code to have more sense, I think you need to spread the Maybe all over the sub-functions, for example in operate, and pop and all other "unsafe" functions, you can take advantage of Maybe type, like divide by 0:
interprete s x
| x `elem` ["+","-","*","/","^"] = operate x s
| x `elem` ["inc","dec","sqrt","sin","cos","inv"] = Just (operate2 x s)
| x `elem` ["+all"] = Just([sum s])
| x `elem` ["dup"] = dup s
| x `elem` ["pop"] = pop s
| x `elem` ["swap"] = swap_first_two_elements s
| x `elem` ["clear"] = Just []
| x `elem` ["*all"] = Just([product s])
| otherwise = Just(read x:s)
pop [] = Nothing
pop (x:xs) = Just xs
dup [] = Nothing
dup s#(x:xs) = Just (x:s)
operate op (x:y:s) = case op of
"+" -> Just(x + y:s)
"-" -> Just(y - x:s)
"*" -> Just( x * y:s)
"/" -> case x of
0 -> Nothing
n -> Just(y / x:s)
"^" -> Just(y ** x:s)
operate _ _ = Nothing
swap_first_two_elements :: [a] -> Maybe [a]
swap_first_two_elements (x:y:xs) = Just (y:x:xs)
swap_first_two_elements _ = Nothing
operate2 = undefined
I don't know what operate2 does, so, I leave it to you. But by sure, it has type [a] -> Maybe [a], so please, make it return a Maybe [a], please.
I would like to count the number of positive integers/elements in the list. This returns the elements with positive values, how can I count the elements? would like to construct something like count(array(...)).
I would like to see a version with i++ and foldl. That would be very helpful.
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Here's a hint: follow the same recursion scheme as before, but return an int at every step.
countPositivesRec :: [Int] -> Int
---
countPositivesRec [] = 0 -- no positives in the empty list
countPositivesRec (x:xs) | x >= 0 = ??
| otherwise = ??
where tl = countPositivesRec xs
One you solve this, it can be rewritten using foldr, if you want.
If you really want to use foldl instead, I would suggest you start by defining a function f such that
f (f (f 0 x0) x1) x2
evaluates to the number of positives in x0,x1,x2. Then you can use foldl f 0 inputList
The function you've written is filter (>=0). As Paul pointed out, the only step remaining is to count and length does that. We can transform the function step by step:
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Observe that xs is only used in the transformed form tl. That's what makes this a right fold.
onlypos1 = foldr maybekeep []
where maybekeep x tl | x >= 0 = x : tl
| otherwise = tl
This operation is known as a filter, keeping only some parts:
onlypos2 = filter dowekeep
where dowekeep x = x >= 0
onlypos3 = filter (\x -> x >= 0)
onlypos4 = filter (>= 0)
But this is of course only one of many possible approaches. For instance, strictness analysis can lead to the conclusion that length is better implemented as foldl' (\a _ -> succ a) 0 than foldr (\_ a -> succ a) 0. Indeed, that is its basic form in the Prelude:
length = foldl' (\c _ -> c+1) 0
We see that the combining function of length ignores the value of one argument, merely requires it to be there. This can naturally be merged with our condition that only some elements count:
lengthFilter1 = length . filter
lengthFilter2 pred = foldl' predCount 0
where predCount c x = if pred x then c+1 else c
countNonNegative = lengthFilter2 nonNegative
where nonNegative x = x >= 0
Incidentally, 0 isn't positive. It's non-negative.
In the end, Haskell's lazy lists mean we can use them to fuse traversals; length . filter (>=0) will only read the input list once, because the only reason it's processing results from filter is that length consumes them. The filtered list never exists as a fully expanded structure, unlike e.g. Python or PHP. This form is likely one of the most readable, but others exist, e.g.:
countNonNegatives xs = sum [1 | x <- xs, x >= 0]
You have
filtering p cons x r = if | p x -> cons x r | otherwise -> r
countPositives = length
. filter (> 0)
= foldr (\x r -> r + 1) 0 -- r++
. foldr (filtering (> 0) (:) ) []
= foldr (filtering (> 0) (\x r -> r + 1)) 0
(since folds fuse by composing their reducer transformers, a-la "fold replaces the cons with a reducer operation, so why create the cons in the first place if it gonna be replaced anyway"), and
filtering (> 0) (\x r -> r + 1) x r
= if | (> 0) x -> (\x r -> r + 1) x r | otherwise -> r
= if | x > 0 -> r + 1 | otherwise -> r
and thus, a version with fold and increment that you wanted,
countPositives = foldr (\x r -> if | x > 0 -> r + 1 | otherwise -> r) 0 -- r++
You can take it from here.
the problem is to check whether parentheses in a string is properly closed or not. For Haskell implementation, so far I have following. It looks quite awkward. I am looking for a more "Haskell-style" or more elegant implementation.
import Data.List
isValidParentheses :: String -> Bool
isValidParentheses = isValidHelper . (filter isParenthese)
getIndex :: (Eq a) => a -> [a] -> Int
getIndex c xs = getOut (elemIndex c xs)
where getOut (Just x) = x
getOut Nothing = -1
isLeftParenthese :: Char -> Bool
isLeftParenthese c = (getIndex c "{[(") /= -1
isRightParenthese :: Char -> Bool
isRightParenthese c = (getIndex c "}])") /= -1
isParenthese :: Char -> Bool
isParenthese c = isLeftParenthese c || isRightParenthese c
isValidHelper :: String -> Bool
isValidHelper xs = helper xs []
where helper (x:xs) [] | isRightParenthese x = False
| otherwise = helper xs [x]
helper [] st = null st
helper (x:xs) (s:ss) | isLeftParenthese x = helper xs (x:s:ss)
| ((getIndex x "}])") /= (getIndex s "{[(")) = False
| otherwise = helper xs ss
Thanks
Loop through the string
Store opening parentheses in stack
Pop matching parentheses out of the stack
Check if stack is empty at the end
isValid = loop []
where
match '(' ')' = True
match '{' '}' = True
match '[' ']' = True
match _ _ = False
loop st [] = null st
loop st (x:xs)
| x `elem` "([{" = loop (x:st) xs
| x `elem` ")]}" = case st of
open : st' | match open x -> loop st' xs
_ -> False -- unmatched close
| otherwise = loop st xs
I have the following code, which I would like to optimize.
I'm particularly unhappy with nub :
deep (Op o x) = [f (Op o x)] ++ map (\y->(Op o y)) (sf x)
deep x = [x]
sf [x] = [[f x]]
sf (x:xs) = map (\y->(y:xs)) (deep x) ++ map (x:) (sf xs)
eqlst l
| l == ll = l
| otherwise = eqlst ll
where ll = nub $ l ++ (concat $ map deep l)
For a full understanding of this, I provide all my code, which is not so long:
module Nat ( Nat, Operator(Add, Mul), Exp(Const, Name, Op), toNat, fromNat) where
import Data.List(nub)
newtype Nat = Nat Integer deriving (Eq, Show, Ord)
toNat :: Integer -> Nat
toNat x | x <= 0 = error "Natural numbers should be positive."
| otherwise = Nat x
fromNat :: Nat -> Integer
fromNat (Nat n) = n
instance Num Nat where
fromInteger = toNat
x + y = toNat (fromNat x + fromNat y)
x - y = toNat (fromNat x - fromNat y)
x * y = toNat (fromNat x * fromNat y)
abs x = x
signum x = 1
data Operator = Add | Sub | Mul
deriving (Eq, Show, Ord)
data Exp = Const Nat | Name { name::String } | Op{ op::Operator, kids::[Exp] }
deriving (Eq, Ord)
precedence :: Exp -> Integer
precedence (Const x) = 10
precedence (Name x) = 10
precedence (Op Add x) = 6
precedence (Op Sub x) = 6
precedence (Op Mul x) = 7
instance Show Exp where
show Op { op = Add, kids = [x, y] } =
let left = if precedence x <= 6 then "(" ++ show x ++ ")" else show x in
let right = if precedence y <= 6 then "(" ++ show y ++ ")" else show y in
left ++ "+" ++ right
show Op { op = Sub, kids = [x, y] } =
let left = if precedence x <= 6 then "(" ++ show x ++ ")" else show x in
let right = if precedence y <= 6 then "(" ++ show y ++ ")" else show y in
left ++ "-" ++ right
show Op { op = Mul, kids = [x, y] } =
let left = if precedence x <= 7 then "(" ++ show x ++ ")" else show x in
let right = if precedence y <= 7 then "(" ++ show y ++ ")" else show y in
left ++ "∙" ++ right
show (Const (Nat x)) = show x
show (Name x) = x
show x = "wat"
instance Num Exp where
fromInteger = Const . toNat
(Const x) + (Const y) = Const (x+y)
x + y = simplify $ Op { op = Add, kids = [x, y] }
(Const x) - (Const y) = Const (x-y)
x - y = simplify $ Op { op = Sub, kids = [x, y] }
(Const x) * (Const y) = Const (x*y)
x * y = simplify $ Op { op = Mul, kids = [x, y] }
abs x = x
signum x = 1
simplify :: Exp -> Exp
simplify (Op Mul [x,1]) = x
simplify (Op Mul [1,x]) = x
simplify (Op Sub [x,y])
| x == y = 0
| otherwise = (Op Sub [x,y])
simplify x = x
f (Op Add [x,y]) = y+x
f (Op Sub [x,y]) = y-x
f (Op Mul [x,y]) = y*x
f x = x
deep (Op o x) = [f (Op o x)] ++ map (\y->(Op o y)) (sf x)
deep x = [x]
sf [x] = [[f x]]
sf (x:xs) = map (\y->(y:xs)) (deep x) ++ map (x:) (sf xs)
eqlst l
| l == ll = l
| otherwise = eqlst ll
where ll = nub $ l ++ (concat $ map deep l)
eq x = eqlst [x]
main = do
let x = Name "x";y = Name "x";z = Name "z";w = Name "w";q = Name "q"
let g = (x+y+(z+w)+q)+(x+y+(z+w)+q)+(x+y+(z+w)+q)+(x+y+(z+w)+q)
putStr $ unlines $ map show $ eq g
I also have a side question, about the function deep and sf that are using f::Exp->Exp. In the end, f should probably be f::[Exp]->[Exp].
Right now, f only performs one kind of transformation. In the end, I would like it to perform many kinds of transformations, for example :
a+b->b+a, (a+b)+c->a+(b+c), etc.
The function nub is inefficient since it only uses an Eq constraint and therefore has to compare every nondiscarded pair of elements. Using the more efficient Data.Set, which is based internally on sorted trees, should improve on this:
import qualified Data.Set as S
eqset s
| s == ss = s
| otherwise = eqset ss
where ss = S.unions $ s : map (S.fromList . deep) (S.toList s)
eqlst = S.toList . eqset . S.fromList