So I have found that the built-in splitAt function in Haskell can be defined as follows:
splitAt :: Int -> [a] -> ([a], [a])
-- Pre: n >= 0
splitAt n []
= ([], [])
splitAt n (x : xs)
= if n == 0
then ([], x : xs)
else (x : xs', xs'')
where
(xs', xs'') = splitAt (n - 1) xs
What I don't understand here/can't get my head around is the where part.
As an example,
splitAt 2 "Haskell" should return (["Ha"],["skell"]), but I don't really understand how it works here to define (x:xs',xs'') as another function? How would this look like visually?
With the example:
splitAt 2 "Haskell"
= (('H':xs',xs''))
^ so this then does splitAt 1 "askell", but I'm very confused as to what happens to the xs',xs'' in the tuple above...
Thanks.
(xs', xs'') = splitAt (n - 1) xs
This takes the result of splitAt (n - 1) xs, which is a pair, and assigns the name xs' to the first element of that pair (i.e. the first n - 1 elements of xs) and xs'' to the second element (i.e. the remaining elements).
(x:xs', xs'')
This produces a pair. The first element of that pair is a list that's the result of prepending x to xs' (i.e. to the first n-1 elements of xs). The second element is xs'' (i.e. the remaining elements of xs).
Related
I have a function which returns a list of halves of palindromes found from the input list. It works if I use an if-statement on one row but I'd like to use guards. Guards give me a parse error. I read many cases giving this kind of error, but I didn't figure out my case. Here is the code:
palindromeHalfs :: [String] -> [String]
palindromeHalfs xs = map firstHalf (filter palindrome xs)
where
firstHalf :: String -> String
firstHalf ys | (length ys) `rem` 2 == 0 = take ((div (length ys 2)) ys
| otherwise = take ((div (length ys 2) + 1) ys
palindrome :: String -> Bool
palindrome str | str == reverse str = True
| otherwise = False
And the error:
palindromeHalfs.hs:6:20: error: parse error on input `otherwise'
|
6 | | otherwise = take ((div (length ys 2) + 1) ys
| ^^^^^^^^^
The function works if I replace
firstHalf ys | (length ys) `rem` 2 == 0 = take ((div (length ys 2)) ys
| otherwise = take ((div (length ys 2) + 1) ys
with
firstHalf ys = if (length (ys !! 0)) `rem` 2 == 0 then take ((div (length (ys !! 0)) 2)) ys
else take ((div (length (ys !! 0)) 2) + 1) ys
In my code the if-statement is one row, it didn't fit here. I'd appreciate if someone can tell me which is preferred, if or guards. And of course, why my guards do not work.
The parentheses are not balanced in
take ((div (length ys 2)) ys
As for style, guards are much preferred over if/else in cases where either may be used. Note also that even :: Integral a => a -> Bool is a function that exists; you don't have to invent it with rem.
I want to reorder a list in the following way:
[5,6,7,8,9] -> [7,5,9,6,8]
[6,7,8,5,4,3] -> [8,5,6,3,7,4]
It's supposed to get the middle number or numbers of the list and put them in the starting position. After that it should start to get the two outer numbers of the list and add them in and work its way in.
I have the following code to get the middle numbers and put them into the beginning of the list but can't figure out how to start adding the outer numbers into the new list.
-- import Data.List
-- import System.IO
longitude xs = length xs
middle xs = length xs `div` 2
addOne xs = middle xs - 1
oneMore xs = length xs - 1
otherCase xs = oneMore xs `div` 2
valuea xs = xs !! middle xs
valueb xs = xs !! addOne xs
valuec xs = xs !! otherCase xs
modulus xs = longitude xs `mod` 2
order xs = midNums xs
takes xs = take (otherCase xs) xs
oddOne xs = otherCase xs + 1
takeX xs = drop (oddOne xs) xs
value xs = takes xs ++ takeX xs
reorder xs = drop (otherCase xs )(take (middle xs + 1) xs)
valueOdd xs = reorder xs ++ takes xs ++ takeX xs
paruno xs = drop (middle xs + 1) xs
pairTwo xs = take (addOne xs) xs
midPair xs = take (addOne xs)(drop (middle xs -1) xs)
--Get the numbers
midNums xs = if modulus xs == 0 then midPair xs ++ paruno xs ++ pairTwo xs
else valueOdd xs
I want it to work like this: Demo
Try this:
f :: (Num a) => [a] -> [a]
f [] = []
f [x] = [x]
f xs = if len `mod` 2 == 1 then flatten [xs !! half] else flatten [xs !! (half-1), xs !! half]
where len = length xs
half = len `div` 2
firsthalf = take (half-1) xs
secondhalf = (reverse . take half . drop (half+1)) xs
outtoin = zipWith (\x y -> x:y:[]) firsthalf secondhalf
flatten = concat . flip (:) outtoin
Breaking it down:
First get the midpoint(s)
Next get the two halves of the list excluding middle elements
Build the list from outside inwards using zip
Concatenate the zip result to flatten and add to the middle elements list
Demo
So I'm learning haskell right now, and I'm having trouble understanding what I'm doing wrong for the following function that emulates zip
1.ziplike xs ys = [(x,y)|c<-[0..(min (length xs) (length ys))-1],x<-xs!!c,y<-ys!!c]
2.ziplike xs ys = [(xs!!c,ys!!c)|c<-[0..(min (length xs) (length ys))-1]]
Now, I know that the correct answer is number 2, but I don't understand why number 1 is wrong for the call ziplike [1,2,3] ['a', 'b', 'c', 'd']. I THINK it's because it's trying to select the index for an individual char, but I'm not sure why.
The error is "Couldn't match expected type ‘[t1]’ with actual type ‘Char’"
To a first approximation:
If e::[a],
and x <- e appears to the right of the | in a list comprehension,
then x :: a wherever it is bound.
This leads to a bit of a problem in your case. You have ys :: [Char] and c :: Int, so that ys!!c :: Char. Hence:
We have ys!!c :: Char
and y <- ys!!c appears to the right of the | in a list comprehension,
so y :: ??? wherever it is bound.
But now we are stuck when trying to write the conclusion about what type y should have: Char is not a list of as, no matter what a we pick.
There are several possible fixes; one is to use let instead of <-, as in
ziplike xs ys = [(x,y)|c<-[0..min (length xs) (length ys)-1],let x=xs!!c; y=ys!!c]
It's a type error.
When you write "x from xs get-index c" (i.e. x <- xs !! c) the thing that you are getting "from" xs !! c is not necessarily a list. It's a technical detail, but it's important. The "from" arrow comes from monad syntax/do-notation. A list comprehension is actually just a do-expression specialized to the List monad; so the right hand side of an arrow <- needs to be a list in the List monad.
You can fix this, first off, by "cheating" with singleton lists, a la:
ziplike xs ys = [ (x,y) | c <- [0 .. min (length xs) (length ys) - 1],
x <- [xs !! c],
y <- [ys !! c]]
So these left-arrows are not "let" variable bindings, but they make Cartesian products: but the Cartesian product of n things with 1 thing with 1 thing is just n * 1 * 1 == n things. So this is great, if a little weird and possibly inefficient.
To do what you were trying to do (bind x and y inside of the list comprehension) you could also write something like:
ziplike xs ys = [let x = xs !! c; y = ys !! c in (x, y)
| c <- [0 .. min (length xs) (length ys) - 1]]
-- or --
ziplike xs ys = [(x, y)
| c <- [0 .. min (length xs) (length ys) - 1],
let x = xs !! c, let y = ys !! c]
-- or --
ziplike xs ys = [(x, y)
| c <- [0 .. min (length xs) (length ys) - 1],
let x = xs !! c; y = ys !! c]
Notice that these are all do-notation ideas tacked together with commas. Of course all of these look more clumsy than
ziplike xs ys = [(xs !! c, ys !! c) | c <- [0..min (length xs) (length ys) - 1]
which does the exact same thing.
With that said, all of this stuff is much more inefficient than the zip function's recursive character: if I double the size of the list, your implementations take 4 times as long to process the whole list; zip only takes twice as long. So be mindful of this "hidden O(n2) factor" in your programming.
I want to write a function that returns every nth element of a given list but then updates the head to the second element and does this again until it has gone through all elements in the list.
I know the code for going through every nth element in a list is:
everyf n [] = []
everyf n as = head as : everyf n (drop n as)
but this does not loop back. How can I get this to update head so that i get the following result:
everyf 3 [1,2,3,4,5,6,7]
returns [[1,4,7],[2,5],[3,6]]
Disclaimer: I don't know haskell (at all) :-)
listOfNths :: Int -> [a] -> [[a]]
listOfNths n xs = map (\x -> everyf n (drop x xs)) [0..n-1]
and a slightly "improved" version:
listOfNths :: Int -> [a] -> [[a]]
listOfNths n xs = map pickEveryf [0..n-1]
where pickEveryf = (everyf n) . (`drop` xs)
From this Youtube video:
> let loeb fs = xs where xs = fmap ($ xs) fs
> loeb [length, (!! 0)]
[2,2]
The xs here is recursively defined, and how loeb terminates is beyond me.
try it:
loeb [length, (!! 0)]
= xs where xs = fmap ($ xs) [length, (!! 0)]
= xs where xs = [length xs, xs !! 0]
so of course length xs is just 2, and so the first element of xs (length xs) is 2 as well.
remember: length xs does not need to evaluate the items of the list:
length [undefined, undefined] = 2
The reason is that length does not evaluate the elements of the list. It simply counts the elements. length is (semantically equivalent) defined as:
length (_:xs) = 1 + length xs
length _ = 0
Even if one of the elements thus comes down on calculating an expression that results in an infinite loop, that doesn't matter. Al long as the list itself is not infinite of course.
Now of you call loeb [length, (!! 0)], it will be evaluated as:
loeb [length, (!! 0)]
xs = fmap ($ xs) [length,(!! 0)]
xs = [length xs,xs !! 0]
Thus the length xs performs lazy evaluation: it is not interested in the value of the elements, so they remain unsolved when counting.