Say I have a list of Strings
["hello", "xbox", "blue"]
And now I want to "insert" (as in create a new immutable list) linefeed characters into the list, but only if the word before ends on a vowel, e.g. a function that creates the following list:
["hello", "\n", "xbox", "blue", "\n"]
What's the most elegant/direct way of doing this in haskell?
One way of doing this would be using do-notation. do-notation on the list monad is a lot like list comprehension, but it also allows you to 'return' multiple elements. Here's my implementation:
solution1 :: [String] -> [String]
solution1 strings = do
str <- strings -- Go through each element of the list
if last str `elem` "aeiou"
then [str, "\n"] -- 'Replace' that element with the element then a newline
else [str] -- Do nothing.
But this is a bit of a weird way of going about things, especially if you're a beginner. The usual way would be recursion, so let's do that instead:
solution2 :: [String] -> [String]
solution2 [] = [] -- Base case: empty list.
solution2 (x:xs) = -- Inductive case: non-empty list.
if last x `elem` "aeiou"
then x : "\n" : solution2 xs -- Recur, reconstructing as we go.
else x : solution2 xs -- Recur, this time with no extra newline.
In reality though, these do basically the same thing—do-notation on lists is basically just an abstraction of the second method.
Something to consider: I used the last function, but this will fail on empty strings. How could you fix that?
Related
I want to create a Haskell function that prints the prefixes of a list:
The function should do the following:
> prefixes "123"
["","1","12"]
> prefixes "1"
[""]
I have written the following code:
prefixes :: [a] -> [[a]]
prefixes [] = []:[]
prefixes f = f : prefixes(init(f))
The function prints the entered string or character as a prefix and prints it in opposite direction. I want to remove it so when I enter "123" it should print as above and display in correct direction.
We can use:
reverse (drop 1 f)
command but I don't know how to implement it in my function.
Can you help me solve this so that it does prints it correctly.
Your base case is incorrect, the empty list has no proper prefixes. So clearly in the base case you must return the empty list for the function to be correct.
Now consider the recursive case. For one, it should always start with the empty list (because the prefixes of (x:xs) are always [[],...]). How can we construct the rest of the list (the non-empty prefixes of (x:xs)?
We want to use recursion, so how do we build the set of non-empty proper prefixes of (x:xs) from the set of proper prefixes of xs? Look at your example "123", the prefixes of "23" are ["", "2"], the non-empty prefixes we want to construct are ["1","12"], so we just add '1' to the head of each prefix of the tail.
So in the recursive case: empty list is a proper prefix, and also the head of the list added to any proper prefix of the tail.
Here is a piece of code that does what you want:
prefixes [] = []
prefixes (x:xs) = [] : map (x:) (prefixes xs)
It looks like you want to know how to define a helper function which would call your original definition.
prefixes xs = reverse (drop 1 (prefixes' xs)) where
prefixes' [] = []:[]
prefixes' f = f : prefixes' (init(f))
Your original definition, while seemingly working, is rather suboptimal though. The other answer shows how to do it more intuotively and without needing a helper function (edit: but the performance may or may not be any good). There are other small things that could be improved in this function:
[]:[] can be written simply as [[]]
drop 1 is tail
parentheses can often be replaced by function composition and $ for better readability.
Here is a solution in point-free style:
prefixes = foldr (\el acc -> [] : map (el:) acc) []
I'm just wondering, for recursion example:
squaresRec :: [Double] -> [Double]
squaresRec [] = []
squaresRec (x:xs) = x*x : squaresRec xs
Why on the recursive case, there is no bracket? Shouldn't it suppose to be like this:
squaresRec :: [Double] -> [Double]
squaresRec [] = []
squaresRec [x:xs] = x*x : squaresRec xs
I know this will not work. But just wondering the explanation behind it.
[] matches the empty list.
[1] matches a list containing exactly one element, and that must be a number equal to one. Note that [1] is actually syntactic sugar for (1:[]), i.e. what this really matches is: a list beginning with the number 1, followed by a list that is empty... which is just a complicated way of saying “a list containing the single element 1”.
(x:xs) matches a list that begins with x, followed by xs (and that may contain any number of elements, possibly zero). I.e. this pattern matches any list with at least one element.
[x:xs] matches again a list which contains exactly one element, and that element should match the pattern (x:xs). (Which doesn't make sense even type-wise, because your lists contain Double-numbers, not lists.)
I had the same problem because I'm coming from Erlang.
The thing to understand is that the [head|tail] pattern we have in Erlang is actually translated by the cons function in Haskell, which is the : operator. The parenthesis are just here to isolate the function parameters, like (3+4) would do.
I know it's tempting to ask "why though???" and that it visually makes more sense, but : is how we build (and separate when pattern-matching) the head and the tail of a linked list.
I'm trying to get permutations of a variable number of strings in a list.. I'm sure this is possible in Haskell, I'm just having a hard time finding a reference for this,
I'm looking to be able to do this [ [n1] ++ [n2] ++ etc | n1 <- {first string}, n2 <- {second string}, etc ]
Where my list might be ["hey", "now"]
and my output would look like this:
["hn","ho","hw","en","eo","ew","yn","yo","yw"]
How would I go about doing something like that?
> sequence ["hey", "now"]
["hn","ho","hw","en","eo","ew","yn","yo","yw"]
sequence is very general, but on lists you can think of it as if it were defined as follows:
sequence :: [[a]] -> [[a]]
sequence [] = [[]]
sequence (x:xs) = [ y:ys | y <- x, ys <- sequence xs ]
The result above is sometimes called the "cartesian product" of a list of lists, since it is similar to that operation on sets.
EDIT: This only works for strings of length 2, but shows the desugaring of the list comprehension (since return is concat and fmap is map, if I recall).
Here's a brute force way of doing it (if you'd like to know a possible approach). If you'd like the clean version, please see chi's answer.
concat $ map (\char1 -> map (\char2 -> char1:[char2]) string2) string1 should do it. There might be a better way with list comprehensions, but this does the job too.
Explanation:
concat $ -- Flatten lists
map (\char1 -> -- Iterate over each character of string1
map (\char2 -> -- Iterate over each character of string2
char1 : [char2] -- Add char1 to char2
) string2
) string1
I have problems trying to separate a list follows, suppose we have the following lists
[[1,2,3,4], [5,6,7,8], [9,10,11,12 ], [13,14,15,16,17]].
The result should be:
[[1,5,9,13] [2,6,10,14] [3,7,11,16] [4,8,12,16]]
I'm trying to do it the following way:
joinHead (x: xs) = map head (x: xs)
separateLists (x: xs) = xs joinHead x ++ separateLists
obviously this does not work. I hope you can help me. thx.
I adapted the functions you wrote, joinHead and separateLists, to make the code work, while preserving the logic you were following. From what I could infer looking at these functions, the idea was to use joinHead to extract the first element of each child list and return a new list. Then, this new list should be inserted in the front of a list of lists returned from calling separateLists recursively.
Here is the new definition of joinHead:
joinHead :: [[a]] -> [a]
joinHead ([]:_) = []
joinHead xs = map head xs
Note that the first line checks, through pattern matching, whether the first list contained in the list of lists is empty and, if so, returns an empty list ([]). The reasons for that are two:
The function head is unsafe. That means that calling head on an empty list will cause an exception to be thrown (try running in GHCi head []);
For simplicity, I'm assuming that all the lists were already checked to have the same length (length (xs !! 0) == length (xs !! 1) ...).
The definition of separateLists is as follows:
separateLists :: [[a]] -> [[a]]
separateLists ([]:_) = []
separateLists ([x]:xs) = [joinHead ([x]:xs)]
separateLists xs = joinHead xs : separateLists (map tail xs)
Again, the first two definitions are necessary for both stopping the recursion and safety purposes. The first line says: "if the first list is empty, then all the elements of all lists were already consumed, so return []". The second line says: "if the first line has exactly one element, then just call joinHead and return the result wrapped in a list". Note that in the third definition we have a call to tail which, like head, throws exceptions when called on []. That's the reason of why we need a separate case for lists of length 1. Finally, the third line, which is executed for lists of length greater than 1, gets a list from joinHead xs and insert it (using the "cons" operator (:)) in the beginning of the list returned from recursively calling separateLists. In this call, we have to take out the first elements of all the lists, that's why we use map tail xs.
Now, running:
λ: let list = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16,17]]
λ: separateLists list
[[1,5,9,13],[2,6,10,14],[3,7,11,15],[4,8,12,16]]
will give you the expected results. I hope it was clear enough. As a final note, I want to point out that this implementation is far from being optimal and, as suggested in the comments, you should probably use the standard Data.List.transpose. As an exercise and didatic example, it's fine! ;-)
I am writing a Haskell function that operates on a list of ByteString values. I need to do a different operation on the first and last items (which may be the same if the list has only one item).
Specifically, I want to write out the following:
"item-1\
\item-2\
\item-3\
...
\item-n"
where item-1 starts with a double quote and ends with a backslash and item-n starts with a backslash and ends with a double quote. All items between item-1 and item-n start and end with backslashes. I am emitting a base64 encoded value as a Haskell String for some code generation. I have already broken the original (long) base64-encoded ByteString into chunks that are 64 characters long each.
I just realized that my question is a dumb one.
I can just use intercalate to inject the "\\\n\\" between the items and then prepend and append a double quote:
import qualified Data.ByteString.Lazy.Char8 as L
(L.pack "\"") `L.append` (L.intercalate "\\\n\\" items) `L.append` (L.pack "\"")
Sample output:
"H4sIAAAAAA\
\AAA2NgAAMm\
\CMXA7JRYxI\
\Am5JafD2Uy\
\AgDvdHs6Lg\
\AAAA==\
\"
You can also consider splitting your list using:
"head" to get the first element of the list
"tail" to get all but the first element of the list
"init" to get all but the last element of the list
"last" to get the last element of the list
So [head a] ++ init (tail a) ++ [last a] == a.
That way, you can change the first and last elements of the list individually and map a function over the "init" part.
I've been in this situation several times and I've never found a good idiomatic solution. Sometimes intercalate isn't enough. Here's one simple solution.
-- | Annotate elements of a list with Bools, the first of which is True if
-- the element is the head of the list, the second of which is True if the
-- element is the last of the list. Both are True for singleton.
markbounds :: [a] -> [(a, Bool, Bool)]
markbounds [] = []
markbounds [x] = [(x, True, True)]
markbounds (x:xs) = (x, True, False) : tailbound xs
where
tailbound [y] = [(y, False, True)]
tailbound (y:ys) = (y, False, False): tailbound ys
For example:
λ> markbounds [1,2,3]
[(1,True,False),(2,False,False),(3,False,True)]
λ> forM_ (markbounds [1,2,3]) $ \(x, isFirst, isLast) -> when isLast $ print x
3
I have build (my first!) library that has a reasonably-generic solution to the "different first and last functions" question. It's on GitHub (https://github.com/davjam/MapWith) and Hackage (http://hackage.haskell.org/package/MapWith).
Initially inspired by James's markbounds function, but can:
work on more general structures than just lists (all Traversable types)
add parameters directly to a function (not just create tuples)
add different types of parameters (first / last / next element / previous element / index from start or end, etc)
allows creation of additional types of parameter.
add any number of parameters
For example:
> andFirstLast [1,2,3]
[(1,True,False),(2,False,False),(3,False,True)]
> mapWithM_ ((\x isL -> when isL $ print x) & isLast) [1,2,3]
3
> mapWith ((,,,) & isLast & prevElt <-^ eltIx) [1,7,4]
[(1,False,Nothing,2),(7,False,Just 1,1),(4,True,Just 7,0)]
More examples at https://github.com/davjam/MapWith/blob/master/doc/examples.hs.
Any feedback would be gratefully received. Thanks!