Having trouble with function in Haskell - haskell

I wrote a function to check if a list matches a condition, and if it does, it prints that value twice. However, in ghc it gives me an error, and i don't understand why...
verifyList f xs = foldl(\x acc -> if f x then x:x:acc else acc) [] xs
Any Help?

Looks like you meant foldr instead of foldl. If I make that change then it works for me.
You could also have done this without folds as
verifyList f xs = concatMap (\x -> [x, x]) $ filter f xs
which I would say more clearly indicates your intent. First filter the list to find all that satisfy f, then duplicate each element.
– bheklilr
Another option based on a comment by leftaroundabout:
verifyList f xs = [y | x <- xs, f x, y <- [x, x]]
My own spin on bheklilr's approach, because I feel like it:
verifyList f xs = filter f xs <**> [id, id]

Related

Rendering values into items and intermediate items in Haskell

While doing user interface programming I often encounter the need to render a list of values and add some related information between the rendered values. In the following code example I'm rendering numerical values into strings where they appear in parenthesis and render the distance of two values into a string that gets placed between the renders of the values. The code works but I'm wondering if an implementation of the mystery function is available as part of the Haskell standard library. I'm also interested in names used for this function in other libraries, as using human readable words makes googling easier.
mystery :: (a -> b) -> (a -> a -> b) -> [a] -> [b]
mystery n d [] = []
mystery n d [x] = [n x]
mystery n d (x:xs) = (n x) : (d x (head xs)) : mystery n d xs
node x = "(" ++ show x ++ ")"
distance x y = "-" ++ (show $ abs $ x - y) ++ "-"
render xs = concat $ mystery node distance xs
-- render [25, 68, 54, 15] == "(25)-43-(68)-14-(54)-39-(15)"
Your mystery function is actually doing a couple things at once, and if you separate out the behaviors, it may be a little easier to see what's going on.
First, you're mapping n on all the elements. We can write that as fmap n xs. Next, you're constructing new elements d x y for all pairs of adjacent elements x and y. We can write that as zipWith d xs (tail xs).
The last step is taking these two constructions and making a new list with elements that alternate back and forth between them. Interestingly, this was a question asked 9 years ago, but still doesn't have a super satisfying answer. Probably the simplest answer is to define your own function:
alternate [] ys = ys
alternate (x:xs) ys = x : alternate ys xs
Then, we can define mystery as a one-liner:
mystery n d x = alternate (fmap n x) (zipWith d x (tail x))
If you really want it to be a one-liner, the best I could come up with was using concat and transpose in a bit of a funky way:
mystery n d x = concat $ transpose $ (pure $ fmap n x) <> (pure $ zipWith d x (tail x))
Basically, we're making singleton lists out of the two components using pure, fusing them together with <>, then transposeing this "list of lists" to get the elements properly interspersed, and concating the result.

Applying functions to lists with substitution

I was trying to make a function that quickly calculates fractions. In my particular case there a factorials, so it s kinda easy. I wrote a make_coprime function which makes two numbers coprime (and returns a pair, which bothers me a little: it sounds a bit too complicated, is there no way to make it return 2 numbers? Looks like there isn't, but just to be sure)
Now it is something like frac{numbers]/{numbers} and I want to make all of the upper ones coprime with all the lower ones.
So I have two lists and I want to apply my function to all possible pairs with substitution after that. This is where I failed. I couldn't even do it with one element and a list, my best was
f a [] = (a, [1])
f a x:xs = ((fst (make_coprime a x)), ((snd (make_coprime a x)):(snd (f (fst (make_coprime a x)) xs))))
(there is a parse error somewhere here, but I can't find it at all)
But I feel like I overcomplicate things. It sounds way simplier than it looks when I write it. Is there an elegant way to do this?
The parsing error is that you've not used parens around x:xs.
Before saying any more: Haskell functions should always come with a type signature, which makes it hugely easier to reason what we're talking about and where any. I'm not sure what you want, but likely
makeCoprime :: Integer -> Integer -> (Integer,Integer)
and
f :: Integer -> [Integer] -> (Integer, [Integer])
Apart from that (and to find other parse errors, which occur before the type system ever takes action), I'd first try to write it as readable as possible. First align everything meaningfully:
f a (x:xs) = ( (fst (make_coprime a x))
, ( (snd (make_coprime a x))
: (snd (f (fst (make_coprime a x)) xs))
)
)
ok, now there are a couple of parens that are not necessary and should be omitted: the , always seperates everything, so you never need to write e.g. (1, (2)): just make it (1,2). And function application binds more tightly than any infix operator, so you also never need to write (f x) : y, just do f x : y. That makes your code
f a (x:xs) = ( fst (make_coprime a x)
, snd (make_coprime a x)
: snd (f (fst (make_coprime a x)) xs)
)
which is already a good deal easier to understand. You could get rid of more parens by using the $ and . operators, but I'll leave that.
What I would definitely not leave, as chepner suggests, are these multiple invokations of make_coprime a x. This kind of duplication is not only code-noise, it can also make your program run very slow.
f a (x:xs) = ( fst axCoprimes
, snd axCoprimes
: snd (f (fst axCoprimes) xs)
)
where axCoprimes = make_coprime a x
Now, all you ever do with axCoprimes is eval the fst and snd components separately. Thus instead of giving the tuple one name, you should immediately match the components:
f a (x:xs) = (p₀, p₁ : snd (f p₀ xs))
where (p₀,p₁) = make_coprime a x
and there you go, that looks very clear IMO.
You only need to call coprime a x once; you can assign its return value to a name using a let statement:
f a (x:xs) = let pair = make_coprime a x
in ((fst pair), ((snd pair):(snd (f (fst pair) xs))))
(Your parse error is likely due to the missing parentheses around x:xs.)
You can simplify it more by unpacking the pair immediately instead of calling fst and snd repeatedly.
f a (x:xs) = let (n1,n2) = make_coprime a x
in (n1, (n2:(snd (f n1 xs))))

Haskell: Double every 2nd element in list

I just started using Haskell and wanted to write a function that, given a list, returns a list in which every 2nd element has been doubled.
So far I've come up with this:
double_2nd :: [Int] -> [Int]
double_2nd [] = []
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)
Which works but I was wondering how you guys would write that function. Is there a more common/better way or does this look about right?
That's not bad, modulo the fixes suggested. Once you get more familiar with the base library you'll likely avoid explicit recursion in favor of some higher level functions, for example, you could create a list of functions where every other one is *2 and apply (zip) that list of functions to your list of numbers:
double = zipWith ($) (cycle [id,(*2)])
You can avoid "empty list" exceptions with some smart pattern matching.
double2nd (x:y:xs) = x : 2 * y : double2nd xs
double2nd a = a
this is simply syntax sugar for the following
double2nd xss = case xss of
x:y:xs -> x : 2 * y : double2nd xs
a -> a
the pattern matching is done in order, so xs will be matched against the pattern x:y:xs first. Then if that fails, the catch-all pattern a will succeed.
A little bit of necromancy, but I think that this method worked out very well for me and want to share:
double2nd n = zipWith (*) n (cycle [1,2])
zipWith takes a function and then applies that function across matching items in two lists (first item to first item, second item to second item, etc). The function is multiplication, and the zipped list is an endless cycle of 1s and 2s. zipWith (and all the zip variants) stops at the end of the shorter list.
Try it on an odd-length list:
Prelude> double_2nd [1]
[1,*** Exception: Prelude.head: empty list
And you can see the problem with your code. The 'head' and 'tail' are never a good idea.
For odd-lists or double_2nd [x] you can always add
double_2nd (x:xs) | length xs == 0 = [x]
| otherwise = x : (2 * head xs) : double_2nd (tail xs)
Thanks.
Here's a foldr-based solution.
bar :: Num a => [a] -> [a]
bar xs = foldr (\ x r f g -> f x (r g f))
(\ _ _ -> [])
xs
(:)
((:) . (*2))
Testing:
> bar [1..9]
[1,4,3,8,5,12,7,16,9]

Haskell - Most frequent value

how can i get the most frequent value in a list example:
[1,3,4,5,6,6] -> output 6
[1,3,1,5] -> output 1
Im trying to get it by my own functions but i cant achieve it can you guys help me?
my code:
del x [] = []
del x (y:ys) = if x /= y
then y:del x y
else del x ys
obj x []= []
obj x (y:ys) = if x== y then y:obj x y else(obj x ys)
tam [] = 0
tam (x:y) = 1+tam y
fun (n1:[]) (n:[]) [] =n1
fun (n1:[]) (n:[]) (x:s) =if (tam(obj x (x:s)))>n then fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s)) else(fun (n1:[]) (n:[]) (del x (x:s)))
rep (x:s) = fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s))
Expanding on Satvik's last suggestion, you can use (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) from Control.Arrow (Note that I substituted a = (->) in that type signature for simplicity) to cleanly perform a decorate-sort-undecorate transform.
mostCommon list = fst . maximumBy (compare `on` snd) $ elemCount
where elemCount = map (head &&& length) . group . sort $ list
The head &&& length function has type [b] -> (b, Int). It converts a list into a tuple of its first element and its length, so when it is combined with group . sort you get a list of each distinct value in the list along with the number of times it occurred.
Also, you should think about what happens when you call mostCommon []. Clearly there is no sensible value, since there is no element at all. As it stands, all the solutions proposed (including mine) just fail on an empty list, which is not good Haskell. The normal thing to do would be to return a Maybe a, where Nothing indicates an error (in this case, an empty list) and Just a represents a "real" return value. e.g.
mostCommon :: Ord a => [a] -> Maybe a
mostCommon [] = Nothing
mostCommon list = Just ... -- your implementation here
This is much nicer, as partial functions (functions that are undefined for some input values) are horrible from a code-safety point of view. You can manipulate Maybe values using pattern matching (matching on Nothing and Just x) and the functions in Data.Maybe (preferable fromMaybe and maybe rather than fromJust).
In case you would like to get some ideas from code that does what you wish to achieve, here is an example:
import Data.List (nub, maximumBy)
import Data.Function (on)
mostCommonElem list = fst $ maximumBy (compare `on` snd) elemCounts where
elemCounts = nub [(element, count) | element <- list, let count = length (filter (==element) list)]
Here are few suggestions
del can be implemented using filter rather than writing your own recursion. In your definition there was a mistake, you needed to give ys and not y while deleting.
del x = filter (/=x)
obj is similar to del with different filter function. Similarly here in your definition you need to give ys and not y in obj.
obj x = filter (==x)
tam is just length function
-- tam = length
You don't need to keep a list for n1 and n. I have also made your code more readable, although I have not made any changes to your algorithm.
fun n1 n [] =n1
fun n1 n xs#(x:s) | length (obj x xs) > n = fun x (length $ obj x xs) (del x xs)
| otherwise = fun n1 n $ del x xs
rep xs#(x:s) = fun x (length $ obj x xs) (del x xs)
Another way, not very optimal but much more readable is
import Data.List
import Data.Ord
rep :: Ord a => [a] -> a
rep = head . head . sortBy (flip $ comparing length) . group . sort
I will try to explain in short what this code is doing. You need to find the most frequent element of the list so the first idea that should come to mind is to find frequency of all the elements. Now group is a function which combines adjacent similar elements.
> group [1,2,2,3,3,3,1,2,4]
[[1],[2,2],[3,3,3],[1],[2],[4]]
So I have used sort to bring elements which are same adjacent to each other
> sort [1,2,2,3,3,3,1,2,4]
[1,1,2,2,2,3,3,3,4]
> group . sort $ [1,2,2,3,3,3,1,2,4]
[[1,1],[2,2,2],[3,3,3],[4]]
Finding element with the maximum frequency just reduces to finding the sublist with largest number of elements. Here comes the function sortBy with which you can sort based on given comparing function. So basically I have sorted on length of the sublists (The flip is just to make the sorting descending rather than ascending).
> sortBy (flip $ comparing length) . group . sort $ [1,2,2,3,3,3,1,2,4]
[[2,2,2],[3,3,3],[1,1],[4]]
Now you can just take head two times to get the element with the largest frequency.
Let's assume you already have argmax function. You can write
your own or even better, you can reuse list-extras package. I strongly suggest you
to take a look at the package anyway.
Then, it's quite easy:
import Data.List.Extras.Argmax ( argmax )
-- >> mostFrequent [3,1,2,3,2,3]
-- 3
mostFrequent xs = argmax f xs
where f x = length $ filter (==x) xs

Is there a way to pattern match against value in the middle of a list? or at the end?

something like
getFirstError :: [Either a b] -> a
getFirstError (x:y:...:Left w:z) = w
wrt Haskell but it might be interesting to know how other languages with pattern matching accomplish this.
You can, despite the other answers, do this using view patterns extension in GHC:
getFirstError ((msum . map test) -> Just x) = x
where test (Left x) = Just x
test (Right x) = Nothing
Alternatively using pattern guards:
getFirstError (xs) | Just x <- (msum $ map test xs) = x
where test (Left x) = Just x
test (Right) x = Nothing
No, but you can use a list comprehension
getFirstError xs = head [ x | Left x <- xs ]
Note that head will fail if there are no errors.
No, there's not. However, you can easiliy write the function using recursion:
getFirstError [] = error "getFirstError: empty list or no error"
getFirstError (Left x : xs) = x
getFirstError (_ : xs) = getFirstError xs

Resources