I am trying to write the function tails, which converts a string into a list of strings in the following way:
tails "abc" = ["abc", "bc", "c", ""]
Here is my implementation:
tails :: [Char] -> [[Char]]
tails (x:xs)
| length (x:xs) == 0 = [""]
| otherwise = (x:xs) : tails xs
As the title suggests, there are non-exhaustive patterns in this function. Unfortunately, I don't see how so.
I am new to Haskell... Any help would be appreciated!
The pattern is non-exhaustive because it can't accept []. A list has form of either [] or a:as, where a is the leading element and as is the list of the trailing elements. So the pattern x:xs matches only if the list has a leading element. Fixing that gives:
tails :: [Char] -> [[Char]]
tails xs
| length xs == 0 = [""]
| otherwise = let (_:xs') = xs in xs : tails xs'
And then xs accepts the list regardless of its form.
But this is inefficient due to length, and doesn't work for infinite lists.
This should fully work, which directly does pattern mathing:
tails :: [Char] -> [[Char]]
tails [] = [""]
tails xs#(_:xs') = xs : tails xs'
What about trying this or at least get some logic from it. It works well.
It's got a helper function to convert the string into a list of separate characters, for example "abc" becomes ["a","b","c"]. It is just less complicated to process them like that and it becomes necessary to collect distinct strings in the result list. There are two functions in the function set and a third is warranted to call the primary function with one parameter. The primary function is on one line but uses guards.
ca = [[c] | c <- "abcdef"]
f (l1,ls) | null ls = l1++[[]] | True = f ( l1 ++ [concat ls], (tail ls))
f ([],ca)
["abcdef","bcdef","cdef","def","ef","f",""]
Edit 4/4/2018
I was wrong. The list parameter does not have to be made into a list before hand. By not doing so, the function becomes simpler by removing the concat function and changing the parameter list from tuple to individual removed lots or parentheses.
fs l1 ls = if null ls then l1++[""] else fs (l1++[ls]) (tail ls)
It is invoked differently, too.
fs [] "Hello!"
This, by itself, produced the right results.
Edit/add 4/11/2018
What keeps recurring (no pun) is dependence on tail when Haskell splits up input into head and tail with (x:xs) they are ready to use. Here is a basic recursive function that uses (x:xs) only for head and tail. I produces all tails of input list including null.
t [] = [""]; t (x:xs) = [x:xs] ++ t xs
And yet another that takes a list as the only parameter.
t ls = [drop n ls|n<-[0..length ls - 1]]
Related
I'm looking for a function f that, given a list of n elements, computes a list of n sublists of length n-1. Furthermore the nth sublist should contain all but the nth element of the original list. E.g:
f [1..4] == [[2,3,4], [1,3,4], [1,2,4], [1,2,3]]
I found a solution that seems to work, but it looks rather unintuitive:
f :: [a] -> [[a]]
f [] = []
f xs = reverse $ go (length xs - 1) xs
where
go 0 _ = [[]]
go n xs = [ y:ys | y:xs' <- tails xs, ys <- go (n-1) xs' ]
Any suggestions for a more comprehensible solution with reasonable performance?
f xs = [ ys ++ zs | (ys, _ : zs) <- zip (inits xs) (tails xs) ]
inits and tails give you all prefixes and suffixes, in order (take a look at the result of zip (inits xs) (tails xs)). The list comprehension takes one element out of each non-empty suffix (_ : zs), and then concatenates the remaining elements together.
You can simplify a lot by observing that the homework problem contains a recursive structure that neatly matches recursion along the list itself. If you pattern match on the input and it's non-empty, it has a first element of the list then the rest of the list. The rest of the list neatly corresponds to the original list without the first element, so it should be the first output. Then comes the recursion - getting the rest of the results is just a straight-forward application of f to the rest of the list and then fixing up the values so they're the right length and start with the right element.
I am trying to separate elements of a list into to further lists, one for the odd and one for even numbers.
For Example,
input: [1,2,3,4,10]
output: ([2,4,10],[1,3])
sepList :: [Int]->([Int],[Int])
sepList [] = ([],[])
sepList (x:xs) | (x mod 2) ==0 = (([x],[]) ++ sepList xs)
| (x mod 2) /=0 = (([],[x]) ++ sepList xs)
| otherwise = ([],[])
It gives error on ...++ sepList xs
anyone could guide me here?
The operator++ is used to concatenate 2 lists and neither of your arguments to ++ is a list,
([x],[]) ++ sepList xs
both ([x],[]) and sepList xs are pairs of lists. So what you want is to pattern match on sepList xs e.g. using a let binding,
let (ys,zs) = sepList xs in
and then return,
(x:ys,zs)
You aren't concatenating two lists; you want to add a single element to a list, selected from the tuple output of the recursive call. Don't use (++); use (:).
sepList (x:xs) = let (evens, odds) = sepList xs
in if even x
then (x:evens, odds)
else (evens, x:odds)
More simply, though, sepList = partition even. (partition can be found in Data.List.)
There are two answers so far which suggest basically doing this by hand (by pattern-matching on the result of the recursive call), but there is actually an operator already defined for the types that you're working with that does exactly what you want! Lists form a monoid with (<>) = (++), but you don't have two lists: you have two pairs of lists. Happily, the type of pairs are also a monoid if each element of the pair is a monoid: (a,b) <> (c,d) = (a <> c, b <> d). So, you can simply replace your ++ call with <>, which will result in concatenating the corresponding lists in your pairs.
For enthusiasts, following one line will also work for separating list in even and odd.
sepList xs = (filter even xs , filter odd xs)
import Data.List
sepList :: [Int]->([Int],[Int])
sepList = partition even
sepList [1,2,3,4,10]
In this case i would use an accumulator to create the tuple containing the two lists.In our case the accumulator is ([],[]).
split::[Int]->([Int],[Int])
split ls= go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
As you can see the elements need to be reversed since we are pushing on top of our lists with the : operator.
I do not know if this is optimal but i would write it like this with reverse:
module Split where
split::[Int]->([Int],[Int])
split ls=let rev tupl=(reverse . fst $ tupl ,reverse .snd $ tupl) in
rev $ go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
I'm reading Real world haskell book again and it's making more sense. I've come accross this function and wanted to know if my interpretation of what it's doing is correct. The function is
oddList :: [Int] -> [Int]
oddList (x:xs) | odd x = x : oddList xs
| otherwise = oddList xs
oddList _ = []
I've read that as
Define the function oddList which accepts a list of ints and returns a list of ints.
Pattern matching: when the parameter is a list.
Take the first item, binding it to x, leaving the remainder elements in xs.
If x is an odd number prepend x to the result of applying oddList to the remaining elements xs and return that result. Repeat...
When x isn't odd, just return the result of applying oddList to xs
In all other cases return an empty list.
1) Is that a suitable/correct way of reading that?
2) Even though I think I understand it, I'm not convinced I've got the (x:xs) bit down. How should that be read, what's it actually doing?
3) Is the |...| otherwise syntax similar/same as the case expr of syntax
1 I'd make only 2 changes to your description:
when the parameter is a nonempty list.
f x is an odd number prepend x to the result of applying oddList to the remaining elements xs and return that result. [delete "Repeat...""]
Note that for the "_", "In all other cases" actually means "When the argument is an empty list", since that is the only other case.
2 The (x:xs) is a pattern that introduces two variables. The pattern matches non empty lists and binds the x variable to the first item (head) of the list and binds xs to the remainder (tail) of the list.
3 Yes. An equivalent way to write the same function is
oddList :: [Int] -> [Int]
oddList ys = case ys of { (x:xs) | odd x -> x : oddList xs ;
(x:xs) | otherwise -> oddList xs ;
_ -> [] }
Note that otherwise is just the same as True, so | otherwise could be omitted here.
You got it right.
The (x:xs) parts says: If the list contains at least one element, bind the first element to x, and the rest of the list to xs
The code could also be written as
oddList :: [Int] -> [Int]
oddList (x:xs) = case (odd x) of
True -> x : oddList xs
False -> oddList xs
oddList _ = []
In this specific case, the guard (|) is just a prettier way to write that down. Note that otherwise is just a synonym for True , which usually makes the code easier to read.
What #DanielWagner is pointing out, is we in some cases, the use of guards allow for some more complex behavior.
Consider this function (which is only relevant for illustrating the principle)
funnyList :: [Int] -> [Int]
funnyList (x1:x2:xs)
| even x1 && even x2 = x1 : funnyList xs
| odd x1 && odd x2 = x2 : funnyList xs
funnyList (x:xs)
| odd x = x : funnyList xs
funnyList _ = []
This function will go though these clauses until one of them is true:
If there are at least two elements (x1 and x2) and they are both even, then the result is:
adding the first element (x1) to the result of processing the rest of the list (not including x1 or x2)
If there are at least one element in the list (x), and it is odd, then the result is:
adding the first element (x) to the result of processing the rest of the list (not including x)
No matter what the list looks like, the result is:
an empty list []
thus funnyList [1,3,4,5] == [1,3] and funnyList [1,2,4,5,6] == [1,2,5]
You should also checkout the free online book Learn You a Haskell for Great Good
You've correctly understood what it does on the low level.
However, with some experience you should be able to interpret it in the "big picture" right away: when you have two cases (x:xs) and _, and xs only turns up again as an argument to the function again, it means this is a list consumer. In fact, such a function is always equivalent to a foldr. Your function has the form
oddList' (x:xs) = g x $ oddList' xs
oddList' [] = q
with
g :: Int -> [Int] -> [Int]
g x qs | odd x = x : qs
| otherwise = qs
q = [] :: [Int]
The definition can thus be compacted to oddList' = foldr g q.
While you may right now not be more comfortable with a fold than with explicit recursion, it's actually much simpler to read once you've seen it a few times.
Actually of course, the example can be done even simpler: oddList'' = filter odd.
Read (x:xs) as: a list that was constructed with an expression of the form (x:xs)
And then, make sure you understand that every non-empty list must have been constructed with the (:) constructor.
This is apparent when you consider that the list type has just 2 constructors: [] construct the empty list, while (a:xs) constructs the list whose head is a and whose tail is xs.
You need also to mentally de-sugar expressions like
[a,b,c] = a : b : c : []
and
"foo" = 'f' : 'o' : 'o' : []
This syntactic sugar is the only difference between lists and other types like Maybe, Either or your own types. For example, when you write
foo (Just x) = ....
foo Nothing = .....
we are also considering the two base cases for Maybe:
it has been constructed with Just
it has been constructed with Nothing
I need to get the nth element of a list but without using the !! operator. I am extremely new to haskell so I'd appreciate if you can answer in more detail and not just one line of code. This is what I'm trying at the moment:
nthel:: Int -> [Int] -> Int
nthel n xs = 0
let xsxs = take n xs
nthel n xs = last xsxs
But I get: parse error (possibly incorrect indentation)
There's a lot that's a bit off here,
nthel :: Int -> [Int] -> Int
is technically correct, really we want
nthel :: Int -> [a] -> a
So we can use this on lists of anything (Optional)
nthel n xs = 0
What you just said is "No matter what you give to nthel return 0". which is clearly wrong.
let xsxs = ...
This is just not legal haskell. let ... in ... is an expression, it can't be used toplevel.
From there I'm not really sure what that's supposed to do.
Maybe this will help put you on the right track
nthelem n [] = <???> -- error case, empty list
nthelem 0 xs = head xs
nthelem n xs = <???> -- recursive case
Try filling in the <???> with your best guess and I'm happy to help from there.
Alternatively you can use Haskell's "pattern matching" syntax. I explain how you can do this with lists here.
That changes our above to
nthelem n [] = <???> -- error case, empty list
nthelem 0 (x:xs) = x --bind x to the first element, xs to the rest of the list
nthelem n (x:xs) = <???> -- recursive case
Doing this is handy since it negates the need to use explicit head and tails.
I think you meant this:
nthel n xs = last xsxs
where xsxs = take n xs
... which you can simplify as:
nthel n xs = last (take n xs)
I think you should avoid using last whenever possible - lists are made to be used from the "front end", not from the back. What you want is to get rid of the first n elements, and then get the head of the remaining list (of course you get an error if the rest is empty). You can express this quite directly as:
nthel n xs = head (drop n xs)
Or shorter:
nthel n = head . drop n
Or slightly crazy:
nthel = (head .) . drop
As you know list aren't naturally indexed, but it can be overcome using a common tips.
Try into ghci, zip [0..] "hello", What's about zip [0,1,2] "hello" or zip [0..10] "hello" ?
Starting from this observation, we can now easily obtain a way to index our list.
Moreover is a good illustration of the use of laziness, a good hint for your learning process.
Then based on this and using pattern matching we can provide an efficient algorithm.
Management of bounding cases (empty list, negative index).
Replace the list by an indexed version using zipper.
Call an helper function design to process recursively our indexed list.
Now for the helper function, the list can't be empty then we can pattern match naively, and,
if our index is equal to n we have a winner
else, if our next element is empty it's over
else, call the helper function with the next element.
Additional note, as our function can fail (empty list ...) it could be a good thing to wrap our result using Maybe type.
Putting this all together we end with.
nth :: Int -> [a] -> Maybe a
nth n xs
| null xs || n < 0 = Nothing
| otherwise = helper n zs
where
zs = zip [0..] xs
helper n ((i,c):zs)
| i == n = Just c
| null zs = Nothing
| otherwise = helper n zs
I've just started to learn Haskell and I am trying to write a simple function that takes a list of strings and reverses each string in the list:
revComp :: [String] -> [String]
revComp [] = []
revComp [x] = [] ++ [reverse x]
revComp (x:xs) = revComp [xs]
When I try to load my code in GHCI, I get an error:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: String
Actual type: [String]
Could anyone explain what and where my problem is? Thanks very much.
The first three lines are fine. Your type signature is correct, the second line is correct, and so is the third. (However, [] ++ [reverse x] is the same as [reverse x].)
The fourth line, however, is wrong. Not only do you not use x at all on the right-hand side, but you have a type error: revComp [xs] calls revComp with a single-element list that has xs as its only element. Here, x is the first element of the list, and xs is the rest of the list. So, since xs has the type [String], [xs] has the type [[String]], but revComp takes a [String]! You want to reverse x, and prepend that to the result of reversing the rest of the list.
You can use revComp xs to reverse each string in the rest of the list, and (:) to prepend a value to a list (with the same syntax seen in the x:xs pattern you used on the left-hand side). That should be enough information for you to fix the last line. This makes the third line redundant, by the way, since [x] is just x:[].
ehird's answer is really complete, but I wanted to point out -- as a reference -- the "good/shorter" way to implement that function in real code, since you're new.
It can be defined as the partial application of map to reverse:
Prelude> let revComp = map reverse
Prelude> revComp ["olleh", "dlrow"]
["hello","world"]
It results in a function revComp :: [[a]] -> [[a]] (and not [String] -> [String] since both map and reverse work on any type of lists) that maps reverse to every element of the input list, returning the list of results.
The third line might not be required even with your example. The edge case (terminating condition) can be only the empty list. You can skip the condition for the single element.
revComp :: [String] -> [String]
revComp [] = []
revComp (x:xs) = reverse x : revComp xs
Don't know if there is a CS term for this. Someone in the community can add that information.
A few more ways to do the same thing:
revstr [] = []
revstr (x:xs) = reverse x : revstr xs
revstr2 [] = []
revstr2 (x:xs) = [reverse x] ++ revstr2 xs
revstr3 xs = map reverse xs
revstr4 = map reverse -- map takes 2 arguments ;)
revstr5 xs = foldl step [] xs
where step acc x = acc ++ [reverse x]
revstr6 xs = foldr step [] xs
where step x acc = reverse x : acc