or takes two values arguments haskell - haskell

I am a beginner in haskell and I tried to define a simple function for Sieve of Eratosthenes but it says
error:
• Couldn't match expected type ‘Bool -> Bool’
with actual type ‘Bool’
• The function ‘or’ is applied to two value arguments,
but its type ‘t Bool -> Bool’ has only one
In the expression: or (mod n x) (divl l x)
In an equation for ‘divl’: divl (n : l) x = or (mod n x) (divl l x)
|
13 | divl (n:l) x = or (mod n x) (divl l x)
erat l [] = l
erat l (x:t) = if divl l x then erat l t else erat (x:t) l
divl (n:l) x = or (mod n x) (divl l x)
divl [] x = True
I tried to write that as an operator with "`" but nothing worked

or is not the boolean OR operator; that's (||). or takes a list (well, Foldable) of Boolean values and returns True if at least one value is True.
> or []
False
> or [True, False]
True
(Note that or [] is defined to be False to preserve the identity or xs || or ys == or (xs ++ ys). As a concrete example, or [] || or [False] == or [False].)

Try to use (||) :: Bool -> Bool -> Bool instead of or :: Foldable t => t Bool -> Bool
https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:-124--124-
https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:or
i.e. mod n x || divl l x or or [mod n x, divl l x].

You need to check if the modulo is zero, or one of the remaining, you use (||) :: Bool -> Bool -> Bool:
divl (n:l) x = mod n x == 0 || divl l x
divl [] x = False
The basecase should be False, otherwise it will always return True. It is probably better to work with any however:
divl ls x = any ((0 ==) . (`mod` x)) ls

at the end summarizing the answers i resolved
erat :: [Int] -> [Int] -> [Int]
erat l [] = l
erat l (x:t) = if divl l x then erat l t else erat (x:l) t
divl (n:l) x = ((mod x n) == 0) || (divl l x)
divl [] x = False

Related

Haskell: How to apply partial order to a substring function?

I have implemented the class POrd and a substring function, which takes 2 strings and determines if the first string is a substring of the second input string.
Now I want to apply the POrd class to the substring function to make it so that the substrings can be partially ordered.
However I am stuck on how to correctly apply the partial order class (POrd) to the substring function.
class Eq a => POrd a where
pocompare :: a -> a -> Maybe Ordering
(~<), (~>), (~<=), (~>=) :: a -> a -> Bool
-- Minimal complete definition: (~<=) | pocompare
pocompare x y | x == y = Just EQ
| x ~<= y = Just LT
| y ~<= x = Just GT
| otherwise = Nothing
x ~<= y = pocompare x y == Just LT
x ~< y = x ~<= y && x /= y
x ~>= y = y ~<= x
x ~> y = x ~>= y && x /= y
substring :: Eq a => [a] -> [a] -> Bool
substring []_= True
substring _[] = False
substring p#(x:xs) (y:ys) = x == y && prefix xs ys || substring p ys
where
prefix [] _= True
prefix _[] = False
prefix (a:as) (b:bs) = a == b && prefix as bs
instance POrd a => POrd [a] where
(~<=) = substring
xs ~<= ys = substring xs ys
xs ~>= ys = substring ys xs

Write haskell function using foldr

I have the following function and should write it with foldr.
f [] = []
f (x:xs)
| x == 0 = case f xs of
[] -> []
ys#(y:_) -> if y == 0 then ys else x : ys
| otherwise = x : f xs
This function basically removes all trailing 0's, but keeps at most one leading 0.
For example:
f [1,2,0,0] = [1,2]
f [1,2,0,1] = [1,2,0,1]
f [0,0,1,0,0,3] = [0,1,0,3]
I have foldr op z lst, but don't know what op can be. z should be [].
Example I traced:
foldr op [] [0,0,1,0,0,3]
-> 0 op (0 op (1 op (0 op (0 op (3 op []))))
|-- [3] ---|
|---[0,3] ------|
|-----[0,3]-----------|
|-----[1,0,3]---------------|
|-----[0,1,0,3]-------------------|
|-----[0,1,0,3]-------------------------|
How about
f = fst . foldr (\ x (xs', y) -> if y && x == 0 then (xs', x==0) else (x:xs', x==0 )) ([], True)
in this case, op returns a tuple of list and Bool, Bool is for tracking whether the accumulated list started with 0. At the end, we use fst to discard the Bool. We have to use ([], True) as the initial value, to handle the trailing zero case.

Haskell: Evalute String containing a simple arithmetic expression to Int

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

How can I extract list of similar elements from a haskell list

Given a list such as [1,0,0,0,3,0,0,0,0,2,4,0,0] and an index, how can I extract consecutive patterns of 0 in Haskell. For example if the given index is between 1 and 3 inclusive, the result is [0,0,0] if it is between 5 and 8 [0,0,0,0] and so on
First, build a list where run lengths are stored for each number:
runs :: (Eq a) => [a] -> [(a, Int)]
runs = map (head &&& length) . group
so e.g.
runs [1,0,0,0,1,0,0,0,0,1,1,0,0] == [(1,1),(0,3),(1,1),(0,4),(1,2),(0,2)]
Then, index into this list by walking it in run length-sized steps:
indexRuns :: Int -> [(a, Int)] -> [a]
indexRuns i [] = error "Index out of bounds"
indexRuns i ((x, l):rs)
| i < l = replicate l x
| otherwise = indexRuns (i - l) rs
You can do this in O(n) time:
extract :: Eq a => Int -> [a] -> [a]
extract _ [] = []
extract idx (x:xs) = extract' x [x] 1 xs
where
extract' _ _ _ [] = [] -- Index out of bounds
extract' v vs n (r : rest)
| idx == n = vs ++ (takeWhile (== v) rest)
| (v == r) = extract' v (r:vs) (n+1) rest
| otherwise = extract' r [r] (n+1) rest
This will count the number of zeros around the index
numZeros::Int->[Int]->Int
numZeros 0 (1:_) = 0
numZeros i (1:rest) = numZeros (i-1) rest
numZeros i theList
| i < zeroLen = zeroLen
| otherwise = numZeros (i-zeroLen) $ drop zeroLen theList
where
zeroLen = length (takeWhile (==0) theList)
You can replicate 0 the appropriate number of times to get the final list.
f = f' (takeWhile (== 0)) where
f' c n xs | n < 0 || null xs = []
f' c n (1:xs) = f (n - 1) xs
f' c 0 xs = c xs
f' c n (0:xs) = f' ((0:) . c) (n - 1) xs
Or even more obfuscated
f n xs = g (splitAt n xs) >>= takeWhile (== 0) where
g (xs, ys#(0:_)) = [reverse xs, ys]
g _ = []
Some tests:
main = mapM_ (\i -> print $ (i, f i [1,0,0,0,1,0,0,0,0,1,1,0,0])) [-1..13]
prints
(-1,[])
(0,[])
(1,[0,0,0])
(2,[0,0,0])
(3,[0,0,0])
(4,[])
(5,[0,0,0,0])
(6,[0,0,0,0])
(7,[0,0,0,0])
(8,[0,0,0,0])
(9,[])
(10,[])
(11,[0,0])
(12,[0,0])
(13,[])

Lambda expression parse error on ")"

My task is to re-implement this function
divn :: Integer -> [Integer] -> [Integer]
divn _ [] = []
divn n (x:xs) | mod x n == 0 = x : divn n xs
| otherwise = divn n xs
using 'foldr'.
What I did:
divn' _ [] = []
divn' n (x:xs) = foldr (\x -> if (mod x n == 0) (x:) ([]++)) [] xs
I thought this would work. Actually it doesn't even compile, but says: "Parse error on input ")".
As I didn't find any errors, I decided to re-write if as if' an now its working...
if' True x _ = x
if' False _ x = x
divn' _ [] = []
divn' n (x:xs) = foldr (\x -> if' (mod x n == 0) (x:) ([]++)) [] xs
Does anyone know where's the error?
Thanks!
if needs a then and an else in Haskell,
(\x -> if (mod x n == 0) (x:) ([]++))
should be
(\x -> if (mod x n == 0) then (x:) else id)
Apart from what Daniel Fischer said, you don't need any separate cases: there's no recursion, the empty list case will be handled by foldr. In your code, the first x is always ignored! Correct is
divn' n xs = foldr (\x -> if x`mod`n == 0 then (x:) else id) [] xs
or, by η-reduction,
divn' n = foldr (\x -> if x`mod`n == 0 then (x:) else id) []
Of course, it would be far more idiomatic to simply do
divn'' n = filter ((==0) . (`mod`n))

Resources