I am trying to write a basic function in Haskell as shown below. My aim is provide the code to square only even numbers while odd numbers will stay same. Would you please help me regarding this issue.
square:: Int -> Int
square x = [ x*x | x <- [1..10], mod x 2 == 0 ]
regards
You are here filtering. You should determine if the number is even or odd and then square the number or not, this can be done in the yield part of the list comprehension.
But the type signature hints that you do not need to construct a list at all. You simply check if the parameter x is even, and if that is the case return x*x, otherwise return x:
square:: Int -> Int
square x = if even x then x*x else x
or through guards:
square:: Int -> Int
square x
| even x = x*x
| otherwise = x
One quite straightforward answer to your question is, you can inline a if statment directly into your list comprehension like so:
[ if even x then x * x else x | x <- [1..10] ]
This is possible since if is an expression in Haskell, meaning it evaluates to a value, so things like this are valid:
let _ = if 1 + 1 == 2 then "foo" else "bar"
It can also be good to look at this problem in another direction. List comprehensions can be quite nice, but sticking an if within it can get pretty messy. Willem's solution of factoring out the method is great, so let's look at other ways we can leverage it with your code:
-- This is the function we're trying to implement
evenSquares :: [Int] -> [Int]
-- We could start by noting that `if` expression has a nice name,
-- which can be factored out to make things look cleaner
-- Same implementation as Willem's
evenSquares xs = [ squareIfEven x | x <- xs ] where
squareIfEven x = if even x then x * x else x
-- List comprehensions are nice, but there's also another name for what we're doing,
-- which is mapping over a collection of values and applying a method
evenSquares xs = map squareIfEven xs where
squareIfEven x = if even x then x * x else x
-- Note how the `xs` is an argument to `evenSquares` and also the last argument to `map`
-- We can actually get rid of `xs` entirely via this rule:
-- https://wiki.haskell.org/Eta_conversion
evenSquares = map squareIfeven where
squareIfEven x = if even x then x * x else x
-- This one's a bit of a stretch, but conceptually quite useful
-- The idea of 'apply a method if a condition is true' can be expressed as a method
-- which takes a predicate method, a transformation method, and a value
-- We can leverage this ourselves to make `squareIfEven` more generic too
evenSquares = map (if' even square id) where
square x = x * x
if' pred fst snd x = if pred x then fst x else snd x
-- There's a bunch more solutions we can try, including things like `do` notation
-- This is just an idea of how you could look at your problem
-- Pick one which makes your solution clear and concise!
Related
I need a little help understanding a comprehension method function.
compdivides :: Integer -> [Integer]
compdivides x
| x > 0 = [a | a <-[1..div x 2], mod x a == 0] ++ [x]
| otherwise = compdivides (abs x)
I understand that if x is positive we do the 3rd line otherwise the 4th line.
In the third line we check whether mod x a == 0 only then do we do everything else.
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here?
Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways?
itemTotal :: [(String, Float)] -> [(String, Float)]
itemTotal [] = []
itemTotal [x] = [x]
I am having some trouble with this as well.
I understand that if the list is empty we simply return an empty list.
However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing?
Thank you so much for the help!
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here?
This is a generator of the list comprehension. The list comprehension:
[ a | a <- [1 .. div x 2 ], mod x a == 0 ]
will evaluate such that a takes each item in the list (so 1, 2, …, x/2), and in case mod x a == 0 (x is dividable by a), it will add a to the list.
Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways?
It appends x at the end of the list. This is done because a number x is always dividable by itself (x), since the a <- [1 .. div x 2] stops at div x 2, it will never check if x divides x.
The function will get stuck in an infinite loop for compdivides 0, so you might want to rewrite the function to cover this case as well.
However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing?
Yes. Usually a pattern like itemTotal (x : xs) = x : itemTotal xs is used where we thus return a list where x is the first item, and we recurse on the tail of the list xs.
Your itemTotal function however only makes a copy of the list for the first two clauses. You thus can simply define itemTotal = id. Likely you will need to rewrite the function to determine the total of the items in the list.
I should write a function that sums elements in a list comprehension block.
Let's take these two functions just for example:
letSum :: [Int] -> [Int]
letSum xs = [result | x <- xs, y <- xs, let result = x + y, result > 10]
normalSum :: [Int] -> [Int]
normalSum xs = [x + y | x <- xs, y <- xs, x + y > 10]
Question:
Is the second function summing x and y twice in opposite to the first one?
If not, how does it work?
The second function will compute the sum twice – there is no explicit sharing to be performed here, nor the Haskell performs memoization (source: When is memoization automatic in GHC Haskell?)
let lets the sum be computed once and used in several places, so the first function will be slightly faster.
EDIT:
Someone in the comments mentioned CSE (common subexpression elimination) as possible optimization that may occur here. I have tried compiling your function with -ddump-cse to discover whether it will happen, but although I didn't find any mentions of normalSum, the output was too mysterious to me. However, my answer should be true if you build your function without -O* flag. I will update my answer if I find more information about it.
I am very new to Haskell, and struggling a bit with a function here. The premise is simple enough: Run through a list, and combine each 3 items next to each other with another function and return a list with the results. The problem is to do it in a nice way.
Here is what I've got:
foo :: [Int] -> [Int]
foo xs
| length xs < 3 = []
| otherwise = n : foo (tail xs)
where n = calc (xs!!0) (xs!!1) (xs!!2)
-- This function is actually significantly more complicated.
calc :: Int -> Int -> Int -> Int
calc x y z = x + y - (z * 2)
-- And we can use it like this:
foo [1,2,3] -- [-3]
foo [1,2,3,4] -- [-3,-3]
foo [1,1,5,3,3] -- [-8,0,2]
What I don't like, is the 5th line, containing all the !!'s. It feels like I'm thinking about it the wrong way, and that there should be a better way of doing this. I'd like to do something like
foo (x:y:z:xs)
-- ...
But that will fail when the list gets less than three items. So, then I'd have to declare other patterns for when the list has fewer items?
Also, in case there is already a function that does what foo does (there probably is, it seems there is one for everything), then I'm not really all that interested in it. I'm trying to grok the Haskell way of doing things, more than expanding my repetoire of functions.
Edit: In JS, I'd do something like n = calc.apply(null, take(3, xs)). I wonder if Haskell has something like apply that takes an array and applies it to a function as parameters.
Edit 2 -- Solution: (based on comment below)
foo (x:y:z:xs) = calc x y z : foo (y:z:xs)
foo _ = []
Last pattern match is a catch-all, so if the first "fails" it will fall through and just return an empty list.
Well, foo (x:y:z:xs) plus a “too short clause” certainly wouldn't be a bad solution. Another would be
foo xs = case splitAt 3 xs of
([x,y,z],xs') -> calc x y z : foo (y:z:xs')
_ -> []
Or, perhaps nicest,
import Data.List (tails)
foo xs = [ calc x y z | (x:y:z:_) <- tails xs ]
I'm playing with Haskell for first time.
I've created function that returns first precise enough result. It works as expected, but I'm using generator for this. How can I replace generator in this task?
integrateWithPrecision precision =
(take 1 $ preciseIntegrals precision) !! 0
preciseIntegrals :: Double -> [Double]
preciseIntegrals precision =
[
integrate (2 ^ power) pi | power <- [0..],
enoughPowerForPrecision power precision
]
You can use the beautiful until function. Here it is:
-- | #'until' p f# yields the result of applying #f# until #p# holds.
until :: (a -> Bool) -> (a -> a) -> a -> a
until p f x | p x = x
| otherwise = until p f (f x)
So, you can write your function like this:
integrateWithPrecision precision = integrate (2 ^ pow) pi
where
pow = until done succ 0
done pow = enoughPowerForPrecision pow precision
In your case, you do all the iteration and then compute a result just once. But until is useful even when you need to compute a result at each step - just use an (iter, result) tuple and then just extract the result at the end with snd.
It seems like you want to check higher and higher powers until you get one that satisfies a requirement. This is what you could do: First you define a function to get enough power, and then you integrate using that.
find gets the first element of a list that satisfies a condition – like being enough of a power! Then we need a fromJust to get the actual value from that. Please note that almost always, fromJust is a terrible idea to have in your code. However, in this case the list is infinite, so we will have troubles with infinite loops long before fromJust is able to crash the program.
enoughPower :: Double -> Int
enoughPower precision =
fromJust $ find (flip enoughPowerForPrecision precision) [0..]
preciseIntegrals :: Double -> Double
preciseIntegrals precision = integrate (2^(enoughPower precision)) pi
The function
\xs -> take 1 xs !! 0
is called head
head [] = error "Cannot take head of empty list"
head (x:xs) = x
Its use is somewhat unsafe, as shown it can throw an error if you pass it an empty list, but in this case since you can be certain your list is non-empty it's fine.
Also, we tend not to call these "generators" in Haskell as they're not a special form but are instead a simple consequence of lazy evaluation. In this case, preciseIntegrals is called a "list comprehension" and [0..] is nothing more than a lazily generated list.
I am trying to write a function to find the index of a given element using tail recursion. Lets say the list contains the numbers 1 through 10, and I am searching for 5, then the output should be 4. The problem I am having is 'counting' using tail recursion. However, I am not even sure if I need to maunally 'count' the number of recursive calls in this case. I tried using !! which does not help because it returns the element in a particular position. I need the the function to return the position of a particular element (the exact opposite).
I have been trying to figure this one out for a hours now.
Code:
whatIndex a [] = error "cannot search empty list"
whatIndex a (x:xs) = foo a as
where
foo m [] = error "empty list"
foo m (y:ys) = if m==y then --get index of y
else foo m ys
Note: I am trying to implement this without using library functions
Your helper function needs an additional parameter for the count.
whatIndex a as = foo as 0
where
foo [] _ = error "empty list"
foo (y:ys) c
| a == y = c
| otherwise = foo ys (c+1)
BTW, it's better form to give this function a Maybe return type instead of using errors. That's how elemIndex works too, for good reason. This would look like
whatIndex a as = foo as 0
where
foo [] _ = Nothing
foo (y:ys) c
| a == y = Just c
| otherwise = foo ys (c+1)
Note: I am trying to implement this without using library functions
This is not a good idea in general. A better exercise is this:
Figure out how to implement it using library functions.
Figure out how to implement whichever library functions you used in step 1 on your own.
This way you're learning three key skills:
What are the standard library functions, and examples of when they are useful.
How to break problems into smaller pieces
How to write basic functions like the ones in the libraries.
In this case, however, your whatIndex is more or less the same function as elemIndex in Data.List, so your problem reduces to writing your own version of this library function.
The trick here is that you want to increment a counter while you recurse down the list. There is a standard technique for writing tail recursive functions, which is called an accumulating parameter. It works like this:
You write an auxiliary function that, compared to the "front-end" function, takes an extra parameter (or more) to keep track of the extra information.
You then define the "real" function as a call to the auxiliary one.
So for elemIndex, the auxiliary function would be something like this (with i as the accumulating parameter for the current element index):
-- I'll leave the blanks for you to fill.
elemIndex' i x [] = ...
elemIndex' i x (x':xs) = ...
Then the "driver" function is this:
elemIndex x xs = elemIndex 0 x xs
But there is a serious problem here that I must mention: getting this function to perform well in Haskell is tricky. Tail recursion is a useful trick in strict (non-lazy) functional languages, but not so much in Haskell, because:
A tail-recursive function in Haskell can still blow the stack,
A non-tail-recursive function can run in constant space.
This older answer of mine shows an example of the second point.
So in your case, a non-tail-recursive solution is probably the easiest one you can give that will run in constant space (i.e., not blow the stack on a long list):
elemIndex x xs = elemIndex' x (zip xs [0..])
elemIndex' x pairs = snd (find (\(x', i) -> x == x') pairs)
-- | Combine two lists by pairing together their first elements, their second
-- elements, etc., until one of the lists runs out.
--
-- EXERCISE: write this function on your own!
zip :: [a] -> [b] -> [(a, b)]
zip xs ys = ...
-- | Return the first element x of xs such that pred x == True. Returns Nothing if
-- there isn't one, Just x if there is one.
--
-- EXERCISE: write this function on your own!
find :: (a -> Bool) -> [a] -> Maybe a
find pred xs = ...