Second to last element of a list in Haskell - haskell

Consider the following function for finding the second-to-last element of a list:
myButLast (x:xs) = if length xs > 1 then myButLast xs else x
This is an O(n^2) algorithm, because length xs is O(n) and is called O(n) times. What is the most elegant way to write this in Haskell such that length stops once it gets past 1, so that the algorithm is O(n)?

The easiest way is to avoid length:
myButLast (x : _ : []) = x -- base case
myButLast (_ : xs) = myButLast xs
The definitive reference on patterns in Haskell is the language report: https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-580003.17
GHC implements a few extensions described at https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-extns.html#pattern-guards.

what about
myButLast [] = error "oho"
myButLast [x,_] = x
myButLast (_:xs) = myButLast xs

Exploiting zip:
\l -> fst . last $ zip l (tail l)
Also available in a pointless, obfuscated style:
fst . last . (zip <*> tail)
or even without parentheses (thanks to #melpomene):
fst . last . ap zip tail
Other variants:
last . ap (zipWith const) tail

Another solution:
myButLast [] = error "List is empty"
myButLast [x] = error "List is a singleton"
myButLast xs = last $ init xs

Another zip-based solution, without exlicitly zipping. Throw in some safety for good measure.
import Data.Maybe
g :: Int -> [a] -> Maybe a
g i = (head <$>) . listToMaybe . reverse -- quick'n'dirty safe-last
. getZipList . traverse ZipList
. sequence [id, drop i]
g 1 [1..10] => Just 9
g 3 [1..10] => Just 7
g 13 [1..10] => Nothing

Here is my solution using the tail function from prelude
myButLast :: [Int] -> Maybe Int
myButLast (x:xs) | ((null xs) || null (tail xs)) = Just x
| otherwise = myButLast(xs)
myButLast [] = Nothing

Related

Get all rotations for a string in haskell

So I'm trying to make a function "rot" which takes a string and returns a list of strings with all possible rotations, e.g rot "abc" returns ["abc", "bca", cab"], seems very simple to do in other languages but I'm a newbie at haskell so I can't think of a way to do it. This is what I have so far:
rot :: [Char] -> [[Char]]
rot word =
let
lst = [tail word ++ [head word]]
in
lst
main = do
print(rot "abc")
It returns me "bca" as expected, but I would like a way to find all rotations and store it in a list.
Here's an example in python
def rot(word):
lst = []
for i in range(len(word)):
newWord1 = word[0:i]
newWord2 = word[i:]
newWordResult = newWord2 + newWord1
lst.append(newWordResult)
return lst
Well, you can more or less directly translate your Python code. Recursion is customarily used in functional programming instead of iteration, and it's more convenient to count from length word down to zero. Other than that, it's pretty much the same:
rot word =
let loop 0 lst = lst
loop i lst =
let newWord1 = take (i-1) word
newWord2 = drop (i-1) word
newWordResult = newWord2 ++ newWord1
in loop (i-1) (newWordResult : lst)
in loop (length word) []
One can make use of the tails and inits of a list:
Prelude Data.List> tails "abc"
["abc","bc","c",""]
Prelude Data.List> inits "abc"
["","a","ab","abc"]
we thus can use this with:
import Data.List(inits, tails)
rotated :: [a] -> [[a]]
rotated xs = [x ++ y | (x#(_:_), y) <- zip (tails xs) (inits xs)]
This produces:
Prelude Data.List> rotated "abc"
["abc","bca","cab"]
Prelude Data.List> rotated [1,4,2,5]
[[1,4,2,5],[4,2,5,1],[2,5,1,4],[5,1,4,2]]
Prelude Data.List> rotated [1.0,3.0,0.0,2.0]
[[1.0,3.0,0.0,2.0],[3.0,0.0,2.0,1.0],[0.0,2.0,1.0,3.0],[2.0,1.0,3.0,0.0]]
or as #Iceland_jack says, we can use the ParallelListComp extension to allow iterating over two lists in parallel in list comprehension without the explicit use of zip:
{-# LANGUAGE ParallelListComp #-}
import Data.List(inits, tails)
rotated :: [a] -> [[a]]
rotated xs = [x ++ y | x#(_:_) <- tails xs | y <- inits xs]
This is, simply,
rotations xs = map (take n) . take n
. tails $ xs ++ xs
where
n = length xs
It is customary to avoid length if at all possible, though here it leads to a bit more convoluted code(*) (but more often than not it leads to a simpler, cleaner code that is more true to the true nature of the problem),
rotations2 xs = map (zipWith (\a b -> b) xs)
. zipWith (\a b -> b) xs
. tails $ xs ++ xs
Testing, we get
> rotations "abcd"
["abcd","bcda","cdab","dabc"]
> rotations2 "abcd"
["abcd","bcda","cdab","dabc"]
> take 4 . map (take 4) $ rotations2 [1..]
[[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]
(*) edit Actually, it probably merits its own name,
takeLength :: [a] -> [b] -> [b]
takeLength = zipWith (\a b -> b)
rotations2 xs = map (takeLength xs)
. takeLength xs
. tails $ xs ++ xs

How does the definition of scanr in terms of foldr work?

Exercise 1 at page 102 of the Haskell Wikibook asks "Write your own definition of scanr, first using recursion, and then using foldr." I wrote a recursive one:
myscan f acc [] = [acc]
myscan f acc (x:xs) = val : rest where
val = f x (head rest)
rest = myscan f acc xs
...but couldn't figure out a foldr version. I eventually Googled and found this answer:
myscan2 f acc xs = foldr f' [acc] xs where
f' x xs = (f x (head xs)) : xs
Obviously it works but it doesn't make sense to me. Using parameters
(+) 0 [1,2,3]
...it becomes something like this:
myscan2 (+) 0 [1,2,3] = foldr f' [0] [1,2,3] where
f' [0] [1,2,3] = ((+) [0] (head [1,2,3])) : [1,2,3]
...but ((+) [0] (head [1,2,3])) part is not type compatible for (+). Yet, the function works, so what am I reading or converting incorrectly?
The matter on the function you found is:
The xs on myscan2 f acc xs = foldr f' [acc] xs is not the same on
f' x xs = (f x (head xs)) : xs.
They are completly diferent. Maybe you could understand better if it looks like:
myscanr f acc xs = foldr f' [acc] xs
where f' b a = (f b (head a)) : a
What it does, change the accumulator to a list, because scanl accumlate but it keep all the path going through the original list. So, f' cons (:) a new head applying the function f to the actual element of the list and the head of accumulator.

Haskell: Avoid using if for permutations?

I was trying to come up with a "one-liner" for generating permutations of a list in Haskell. This is what I have so far:
perms xs = if length xs == 0 then [[]] else [x:ys | x <- xs, ys <- perms $ delete x xs]
The problem is that I am having to use if which I don't like very much in Haskell. Is it possible to avoid using if, or a multi-part definition, or a case statement etc. and only "higher-order" functions (e.g. foldr etc.) to achieve this? (and also ideally keep it relatively small one-liner)
If you find it satisfactory to just get rid of the if without any interesting changes to the function, base-4.7.0.0 (bundled with GHC 7.8) includes bool in Data.Bool.
perms xs = bool [[]] [x:ys | x <- xs, ys <- perms $ delete x xs] $ not (null xs)
I manage to implement this perms by using foldr, but it becomes more complex. It is hardly to believe this is what you are looking for:
perms xs = filter (\l -> length l == length xs) $ foldr step [[]] xs
where step x acc = (map (x:) . perms $ delete x xs) ++ acc
[ghci] let perms1 xs = [x:ys | x <- xs, (not . null) xs ,ys <- perms $ delete x xs]
[ghci] perms1 []
[]
[ghci] perms1 [1,2,3]
[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
The higher function you need is the one that does the same thing as your if expression: check a given predicate, if true, then evaluate to expression1, else evaluate to expression2.
I didn't find this in the standard library, but this is the function you are looking for:
myBranchFunction :: t -> t -> [a] -> t
myBranchFunction e1 e2 xs = if length xs == 0 then e1 else e2
(you could generalize this further by having length be an argument to myBranchFunction if you would like.)
Then you could define perms' like so:
perms' :: Eq a => [a] -> [[a]]
perms' xs = myBranchFunction [[]] [x:ys | x <- xs, ys <- perms $ delete x xs] xs
Note that all we are doing is moving the if expression out to another function. For this function, however, I think I would prefer not to try to fit it on one line and just use a case expression for readability.

implementation of unzip function in haskell

I am trying to implement the unzip function, I did the following code but I get error.
myUnzip [] =()
myUnzip ((a,b):xs) = a:fst (myUnzip xs) b:snd (myUnzip xs)
I know that problem is in the right side of the second line but I do know how to improve it .
any hint please .
the error that I am getting is
ex1.hs:190:22:
Couldn't match expected type `()' with actual type `[a0]'
In the expression: a : fst (myUnzip xs) b : snd (myUnzip xs)
In an equation for `myUnzip':
myUnzip ((a, b) : xs) = a : fst (myUnzip xs) b : snd (myUnzip xs)
ex1.hs:190:29:
Couldn't match expected type `(t0 -> a0, b0)' with actual type `()'
In the return type of a call of `myUnzip'
In the first argument of `fst', namely `(myUnzip xs)'
In the first argument of `(:)', namely `fst (myUnzip xs) b'
ex1.hs:190:49:
Couldn't match expected type `(a1, [a0])' with actual type `()'
In the return type of a call of `myUnzip'
In the first argument of `snd', namely `(myUnzip xs)'
In the second argument of `(:)', namely `snd (myUnzip xs)'
You could do it inefficiently by traversing the list twice
myUnzip [] = ([], []) -- Defaults to a pair of empty lists, not null
myUnzip xs = (map fst xs, map snd xs)
But this isn't very ideal, since it's bound to be quite slow compared to only looping once. To get around this, we have to do it recursively
myUnzip [] = ([], [])
myUnzip ((a, b):xs) = (a : ???, b : ???)
where ??? = myUnzip xs
I'll let you fill in the blanks, but it should be straightforward from here, just look at the type signature of myUnzip and figure out what you can possible put in place of the question marks at where ??? = myUnzip xs
I thought it might be interesting to display two alternative solutions. In practice you wouldn't use these, but they might open your mind to some of the possibilities of Haskell.
First, there's the direct solution using a fold -
unzip' xs = foldr f x xs
where
f (a,b) (as,bs) = (a:as, b:bs)
x = ([], [])
This uses a combinator called foldr to iterate through the list. Instead, you just define the combining function f which tells you how to combine a single pair (a,b) with a pair of lists (as, bs), and you define the initial value x.
Secondly, remember that there is the nice-looking solution
unzip'' xs = (map fst xs, map snd xs)
which looks neat, but performs two iterations of the input list. It would be nice to be able to write something as straightforward as this, but which only iterates through the input list once.
We can nearly achieve this using the Foldl library. For an explanation of why it doesn't quite work, see the note at the end - perhaps someone with more knowledge/time can explain a fix.
First, import the library and define the identity fold. You may have to run cabal install foldl first in order to install the library.
import Control.Applicative
import Control.Foldl
ident = Fold (\as a -> a:as) [] reverse
You can then define folds that extract the first and second components of a list of pairs,
fsts = map fst <$> ident
snds = map snd <$> ident
And finally you can combine these two folds into a single fold that unzips the list
unzip' = (,) <$> fsts <*> snds
The reason that this doesn't quite work is that although you only traverse the list once to extract the pairs, they will be extracted in reverse order. This is what necessitates the additional call to reverse in the definition of ident, which results in an extra traversal of the list, to put it in the right order. I'd be interested to learn of a way to fix that up (I expect it's not possible with the current Foldl library, but might be possible with an analogous Foldr library that gives up streaming in order to preserve the order of inputs).
Note that neither of these work with infinite lists. The solution using Foldl will never be able to handle infinite lists, because you can't observe the value of a left fold until the list has terminated.
However, the version using a right fold should work - but at the moment it isn't lazy enough. In the definition
unzip' xs = foldr f x xs
where
f (a,b) (as,bs) = (a:as, b:bs) -- problem is in this line!
x = ([], [])
the pattern match requires that we open up the tuple in the second argument, which requires evaluating one more step of the fold, which requires opening up another tuple, which requires evaluating one more step of the fold, etc. However, if we use an irrefutable pattern match (which always succeeds, without having to examine the pattern) we get just the right amount of laziness -
unzip'' xs = foldr f x xs
where
f (a,b) ~(as,bs) = (a:as, b:bs)
x = ([], [])
so we can now do
>> let xs = repeat (1,2)
>> take 10 . fst . unzip' $ xs
^CInterrupted
<< take 10 . fst . unzip'' $ xs
[1,1,1,1,1,1,1,1,1,1]
Here's Chris Taylor's answer written using the (somewhat new) "folds" package:
import Data.Fold (R(R), run)
import Control.Applicative ((<$>), (<*>))
ident :: R a [a]
ident = R id (:) []
fsts :: R (a, b) [a]
fsts = map fst <$> ident
snds :: R (a, b) [b]
snds = map snd <$> ident
unzip' :: R (a, b) ([a], [b])
unzip' = (,) <$> fsts <*> snds
test :: ([Int], [Int])
test = run [(1,2), (3,4), (5,6)] unzip'
*Main> test
([1,3,5],[2,4,6])
Here is what I got working after above guidances
myUnzip' [] = ([],[])
myUnzip' ((a,b):xs) = (a:(fst rest), b:(snd rest))
where rest = myUnzip' xs
myunzip :: [(a,b)] -> ([a],[b])
myunzip xs = (firstValues xs , secondValues xs)
where
firstValues :: [(a,b)] -> [a]
firstValues [] = []
firstValues (x : xs) = fst x : firstValues xs
secondValues :: [(a,b)] -> [b]
secondValues [] = []
secondValues (x : xs) = snd x : secondValues xs

Haskell pair and unpair functions

I have the following two functions written.
pair :: [a] -> [(a, a)]
pair [] = []
pair [x] = []
pair (x1:x2:xs) = (x1, x2) : pair xs
unpair :: [(a, a)] -> [a]
unpair [] = []
unpair ((x1, x2):xs) = x1 : x2 : unpair xs
Pair will take pairs of elements and make 2-tuples of them. If the list has an odd number of elements, discard the last one. Unpair is the reverse of pair.
These work, but wondering whether there is a more succinct way to write these.
One-liners:
pair xs = map snd . filter fst . zip (iterate not True) $ zip xs (drop 1 xs)
unpair = concatMap (\(x,y) -> [x,y])
You could have also abbreviate your definition of pair a little:
pair (x1:x2:xs) = (x1, x2) : pair xs
pair _ = []
It's not any more concise, but for the sake of clarity I'd use splitEvery from Data.List.Split for pair:
pair = map tuplify . filter ((>1) . length) . splitEvery 2
where
tuplify [x, y] = (x, y)
This is off the top of my head—it would be nicer to check the length of the last list only.
For unpair I'd use foldr to avoid the explicit recursion:
unpair = foldr (\(x, y) -> (x:) . (y:)) []
This is just a matter of taste.
So many possibilities. How about these?
unpair' = concatMap (\(x,y) -> [x,y])
pair' xs = map snd . filter fst . zip (cycle [True, False]) $ zip xs (tail xs)
pair'' xs = [(x,y) | (True,x,y) <- zip3 (cycle [True,False]) xs (tail xs)]
The two versions of pair should be the same.
Edit: Regarding my comment above, one can use the split package from Hackage to write:
pair xs = map head . splitEvery 2 $ zip xs (tail xs)
which is closer to the desired
pair xs = everyOther $ zip xs (tail xs)
But, in the spirit of pointlessness, I think we should probably all agree on writing it,
pair = map head . splitEvery 2 . (zip <$> id <*> tail)
to ensure confusion.
pair s = dropEven $ zip s (tail s)
where dropEven s = map fst $ filter snd $ zip s (cycle [True, False])
unpair = concatMap (\(a, b) -> [a, b])
Though I definitely prefer your definition of pair.
This is a nice use for view patterns:
{-# LANGUAGE ViewPatterns #-}
pair :: [a] -> [(a,a)]
pair (splitAt 2 -> ([x,y],ys)) = (x,y) : pair ys
pair _ = []
unpair :: [(a,a)] -> [a]
unpair = (>>= \(x,y) -> [x,y])

Resources