So I have this function
listSet :: [a] -> Integer -> a -> [a]
listSet l n x =
let (xs,_:ys) = splitAt n l
xs ++ x : ys
But I'm getting an error:
:25:9: parse error in let binding: missing required 'in'
What am I missing to resolve this?
And is my logic correct to split at nth position and adding a element at the beginning of the list?
Any help on the error or on the code would be appreciated!
EDIT: Is there anyway to make this code work without changing Integer to Int?
yes your idea is right - there are just two problems:
as Jubobs said you need a in if you use let outside a do block, as this is an expression let ... in ... (see below)
you have a slight type problem: splitAt want's an Int:
listSet :: [a] -> Int -> a -> [a]
listSet l n x =
let (xs,_:ys) = splitAt n l
in xs ++ x : ys
this should work
of course there are a few problems with your solution:
if n is greater than your list your function will fail (example listSet [1..4] 5 99)
the ++ is not very performant for larger lists - and you can do without if you extent on splitAts implementation (see below)
as you asked: yes there is an easy way: you can for example just write it in the obvious recursive style - this will even remove the ++ and needed splitAt:
listSet :: [a] -> Integer -> a -> [a]
listSet [] _ _ = []
listSet (_:xs) 0 y = y:xs
listSet (x:xs) n y = x:listSet xs (n-1) y
or you can use your version with the genericSplitAt - but please note the above problems
Related
Ok, hi everyone. I've been trying this for a liitle while now with no success. What I want to do is get the middle number(s) of a list move them over to the starting position of the list. For example:
[5,6,8,9,0] => [8,5,6,9,0] //The 8 was moved over to the starting position.
[5,6,7,8] => [6,7,5,8] //The two middle numbers were moved to the starting position.
So far i've been able to get the two middle numbers of the list (code below) but that's where I get stuck and don't know how to move the numbers over.
My code:
middle :: [a] -> [a]
middle xs = take (signum ((l + 1) `mod` 2) + 1) $ drop ((l - 1) `div ` 2) xs
where l = length xs
I would recommend doing it like this:
splitMiddle :: [a] -> ([a], [a], [a])
Where it would return
(beginning, middle, end)
then you can just do
middleToFront :: [a] -> [a]
middleToFront xs
let (beginning, middle, end) = splitMiddle xs
in middle ++ beginning ++ end
To implement splitMiddle, I'd recommend breaking it up into a few steps
-- This is actually available in Data.List more efficiently,
-- but you can implement it yourself for practice
splitAt :: Int -> [a] -> ([a], [a])
splitAt n xs = (take n xs, drop n xs)
splitMiddle :: [a] -> ([a], [a], [a])
splitMiddle xs =
let l = length xs
beginningLength = ???
(beginning, rest) = splitAt beginningLength xs
middleLength = ???
(middle, end) = ???
in (beginning, middle, end)
You'll need to fill in the ???s, I'm not going to solve all of it for you ;)
You can use (:) to prepend that item to the front of the list. For the odd length case, you can do this as follows:
(xs !! middleLoc):(take middleLoc xs ++ drop (middleLoc + 1) xs)
where
middleLoc = l `quot` 2
You will have to modify this for the even length case, which you might want to identify and deal with separately (ie- pull out and prepend two items). I'll leave that for you to add.
I'm trying to solve this problem. This function takes two parameters. The first is a function that returns a boolean value, and the second is a list of numbers. The function is supposed to remove the first value in the second parameter that returns true when run with the first parameter.
There's a second function, which does the same thing, except it removes the last value that satisfies it, instead of the first.
I'm fairly certain I have the logic down, as I tested it in another language and it worked, my only problem is translating it into Haskell syntax. Here's what I have:
removeFirst :: (t -> Bool) -> [t] -> [t]
removeFirst p xs = []
removeFirst p xs
| p y = ys
| otherwise = y:removeFirst p ys
where
y:ys = xs
removeLast :: (t -> Bool) -> [t] -> [t]
removeLast p xs = []
removeLast p xs = reverse ( removeFirst p ( reverse xs ) )
I ran:
removeFirst even [1..10]
But instead of getting [1,3,4,5,6,7,8,9,10] as expected, I get [].
What am I doing wrong?
removeFirst p xs = []
This always returns the empty list and it matches all arguments. I think you mean this.
removeFirst _ [] = []
Your first equation,
removeFirst p xs = []
says „Whatever my arguments are, just return []“, and the rest of the code is ignored.
You probably mean
removeFirst p [] = []
saying „When the list is already empty, return the empty list.“
I'm writing a combs function in haskell
what it needs to do is, when I provide it with a deck of cards, give me every combination of hands possible from that deck of size x
This is the relevant code
combs :: Int -> [a] -> [[a]]
combs 0 _ = [[ ]]
combs i (x:xs) = (filter (isLength i) y)
where y = subs (x:xs)
combs _ _ = [ ]
isLength :: Int -> [a] -> Bool
isLength i x
| length x == i = True
| otherwise = False
subs :: [a] -> [[a]]
subs [ ] = [[ ]]
subs (x : xs) = map (x:) ys ++ ys
where ys = subs xs
However, when I ask it to compute a combs 5 [1..52], e.g. a hand of 5 out of a full deck, it does not provide a result, and keeps running for a really long time
Does anyone know what the problem is and how to speed up this algorithm?
To extract i items from x:xs you can proceed in two ways:
you keep the x, and extract only i-1 elements from xs
you discard x, and extract all the i elements from xs
Hence, a solution is:
comb :: Int -> [a] -> [[a]]
comb 0 _ = [[]] -- only the empty list has 0 elements
comb _ [] = [] -- can not extract > 0 elements from []
comb i (x:xs) = [ x:ys | ys <- comb (i-1) xs ] -- keep x case
++ comb i xs -- discard x case
By the way, the above code also "proves" a well-known recursive formula for the binomial coefficients. You might already have met this formula if you attended a calculus class.
Letting B(k,n) = length (comb k [1..n]), we have
B(k+1,n+1) == B(k,n) + B(k+1,n)
which is just a direct consequence of the last line of the code above.
Right now it's a bit hard to see what you are trying to do - but I guess the problems you have is that you gonna filter and map a lot.
I think a simple way to get what you need is this:
module Combinations where
import Data.List (delete)
combs :: Eq a => Int -> [a] -> [[a]]
combs 0 _ = [[]]
combs i xs = [ y:ys | y <- xs, ys <- combs (i-1) (delete y xs) ]
which uses delete from Data.List
It should be lazy enough to find you combinations quick - of course all will take a while ;)
λ> take 5 $ combs 5 [1..52]
[[1,2,3,4,5],[1,2,3,4,6],[1,2,3,4,7],[1,2,3,4,8],[1,2,3,4,9]]
how does it work
it's one of those recursive combinatorial algorithm that works by selecting a first card y from all the cards xs, and then recursivley gets the rest of the handysfrom the deck without the selected carddelete a xsand then putting it back togethery:ys` inside the list-monad (here using list-comprehensions).
BTW: ther are 311,875,200 such decks ;)
version without list-comprehensions
here is a version without comprehensions in case your system has issues here:
combs :: Eq a => Int -> [a] -> [[a]]
combs 0 _ = [[]]
combs i xs = do
y <- xs
ys <- combs (i-1) (delete y xs)
return $ y:ys
version that will remove permutations
this one uses Ord to get sort the items in ascending order and in doing so removing duplciates in respect to permutaion - for this to work xs is expected to be pre-sorted!
Note chi's version is working with fewer constraints and might be more preformant too - but I thougt this is nice and readable and goes well with the version before so maybe it's of interest to you.
I know it's not a thing often done in Haskell/FP where you strife for the most general and abstract cases but I come form an environment where most strive for readability and understanding (coding for the programmer not only for the compiler) - so be gentle ;)
combs' :: Ord a => Int -> [a] -> [[a]]
combs' 0 _ = [[]]
combs' i xs = [ y:ys | y <- xs, ys <- combs' (i-1) (filter (> y) xs) ]
My professor gave me an example to get last element in the list using "laste" function:
he stated that: definition in the form of “laste xs = …” is not acceptable, whereas definition in the form of “laste = …” is acceptable.
I have tried something like this: Please correct me if my solution is wrong according to problem statement.
laste :: [a] -> Maybe a
laste [] = Nothing
laste (x:[]) = Just x
laste (x:xs) = laste xs
But this gives me answer for example:
ghci>laste[1,2,3,4]
Just 4
I want to get rid of this "Just".
Is there any solution to remove Just?
You would need to change the signature of the function to return a simple element.
The thing is that you would need to return an error in case of empty list.
laste :: [a] -> a
laste [] = error "Can't handle empty lists." -- or some other error message
laste [x] = x
laste (x:xs) = laste xs
While Charmini2's answer is functionally correct, it doesn't solve the problem of retrieving the last element in pointfree form. Consider
laste :: [a] -> a
laste = foldr1 (\_ a -> a)
It works according to specs as foldr1 expects a non-empty list. Intuition for why it returns the last element in the list can be gotten from the observation that foldr1 replaces every (:) in the structure of the list with the lambda in the above equation, which basically selects the rightmost of two elements. Repeat, and you get the last.
I think your professor meant was that you need to re-implement the Prelude function last
in a point-free style.
non point-free example:
filterEven xs = filter even xs
point-free exapmle:
filterEven = filter even
point-free examples of last:
lastv1 = (head . reverse)
lastv2 = foldl1 (\acc x -> x)
lastv3 = foldr1 (\x acc -> acc)
lastv4 = \(x:xs) -> if null xs then x else lastv4 xs
lastv5 = \e -> case e of
[x] -> x
(_:xs) -> lastv5 xs
otherwise -> error "empty list"
Here a possible working solution:
last' :: [a] -> a
last' [] = error "empty"
last' (x:[]) = x
last' (x:xs) = last' xs
The function I'm trying to write should remove the element at the given index from the given list of any type.
Here is what I have already done:
delAtIdx :: [x] -> Int -> [x]
delAtIdx x y = let g = take y x
in let h = reverse x
in let b = take (((length x) - y) - 1) h
in let j = g ++ (reverse b)
in j
Is this correct? Could anyone suggest another approach?
It's much simpler to define it in terms of splitAt, which splits a list before a given index. Then, you just need to remove the first element from the second part and glue them back together.
reverse and concatenation are things to avoid if you can in haskell. It looks like it would work to me, but I am not entirely sure about that.
However, to answer the "real" question: Yes there is another (easier) way. Basically, you should look in the same direction as you always do when working in haskell: recursion. See if you can make a recursive version of this function.
Super easy(I think):
removeIndex [] 0 = error "Cannot remove from empty array"
removeIndex xs n = fst notGlued ++ snd notGlued
where notGlued = (take (n-1) xs, drop n xs)
I'm a total Haskell noob, so if this is wrong, please explain why.
I figured this out by reading the definition of splitAt. According to Hoogle, "It is equivalent to (take n xs, drop n xs)". This made me think that if we just didn't take one extra number, then it would be basically removed if we rejoined it.
Here is the article I referenced Hoogle link
Here's a test of it running:
*Main> removeIndex [0..10] 4
[0,1,2,4,5,6,7,8,9,10]
deleteAt :: Int -> [a] -> [a]
deleteAt 0 (x:xs) = xs
deleteAt n (x:xs) | n >= 0 = x : (deleteAt (n-1) xs)
deleteAt _ _ = error "index out of range"
Here is my solution:
removeAt xs n | null xs = []
removeAt (x:xs) n | n == 0 = removeAt xs (n-1)
| otherwise = x : removeAt xs (n-1)
remove_temp num l i | elem num (take i l) == True = i
| otherwise = remove_temp num l (i+1)
remove num l = (take (index-1) l) ++ (drop index l)
where index = remove_temp num l 1
Call 'remove' function with a number and a list as parameters. And you'll get a list without that number as output.
In the above code, remove_temp function returns the index at which the number is present in the list. Then remove function takes out the list before the number and after the number using inbuilt 'take' and 'drop' function of the prelude. And finally, concatenation of these two lists is done which gives a list without the input number.