So i created this function , to give me the "n" first elements from a list,"(b:bs);
1 module Sexta where
2
3 take6::Int->[a]->[a]
4 take6 n (b:bs) = if n<=0 then []
5 else [b] ++ (take6 (n-1) bs)
The problem is that when i try: take6 2 [], it shows:
*** Exception: sexta.hs:(4,1)-(6,15): Non-exhaustive patterns in function take6
I dont why, cuz when i try this by hand :
take6 2 []
= [] ++take6 1 []
= [] ++[]++take6 0 []
= [] ++[]++[]
= []
In your program you write:
take6 n (b:bs) = ...
But here you thus use a pattern (b:bs) which is the "cons" constructor of the list. The cons constructor takes a head b and a tail bs. The list type has however two constructors: the "cons" we already discussed here, and the empty list []. Haskell is complaining that it can not find a clause for the empty list pattern of the second argument. So your function needs to be defined with a shape:
take6 n [] = ...
take6 n (b:bs) = ...
Now the question is still what to do here. Regardless of what we take in case of an empty list, we can not emit any elements anymore, so you probably want to return the empty list, so:
take6 _ [] = []
furthermore you make indeed a distinction between n being less than or equal to zero in which case the result is an empty list:
take6 n (b:bs) | n <= 0 = []
but there is also a case where n > 0. In that case we want indeed prepend b to the take6 (n-1) bs. Mind however that a more efficient way to prepend, is again using the "cons" constructor:
| otherwise = b : take6 (n-1) bs
or in full:
take6 :: Int -> [a] -> [a]
take6 _ [] = []
take6 n (b:bs) | n <= 0 = []
| otherwise = b : take6 (n-1) bs
The pattern b:bs does not match the empty list. You need a separate case to handle the empty list.
You're destructuring the list before you check n, so even if it's 0 you're requiring the list be non-empty. You could use a guard to handle that case, but that wouldn't help in this case where the list is too short.
Related
I want it to show the desired n final numbers, but the GHCi is giving an error in the code
nLast :: int -> [a] -> [a]
nLast 0 _ = []
nLast _ [] = []
nLast n (x:xs) = nultimos (n-1) xs
You can work with two enumerators over the list. You give one of the enumeraters a head start of n items and each time you let both the enumerators make one hope. If the first runner reaches the empty list, then we know that the second runner has n items they still need to enumerate over.
We thus can implement this with:
nLast :: Int -> [a] -> [a]
nLast n ls = go (drop n ls) ls
where go (_:xs) (_:ys) = …
go [] ys = …
here you still need to fill in the … parts. I leave this as an exercise.
In the above example there is a pattern that we do not cover, a pattern where the first list is a non-empty list (_:_) and the second is empty []. We know that this can never happen, it might still be better however to add a clause for this.
I am still trying to grasp the way Haskell and Functional Programming works, and I need help understanding why my function is not working. I am trying to create a function that takes a list of integers as a parameter and filters out/returns a sublist which contains any multiples of 3 from the first list. Here is my code:
module Main where
sublist = []
myFunc :: [Int] -> [Int]
myFunc [] = []
myFunc [t] = do
if t `mod` 3 == 0
then t : sublist
else myFunc []
myFunc (h:t) = do
if h `mod` 3 /= 0
then myFunc t
else do
h : sublist
myFunc t
This only returns a list containing the last value passed to the function, and still sublist = []. Thanks for any advice you can give me in advance.
I think you need to first switch over mentally to functional style.
for example, this is to get even numbers from a list
> filter even [1..10]
[2,4,6,8,10]
without using the existing functions you can implement the same functionality
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' condition (x:xs) = if condition x
then x : filter' condition xs
else filter' condition xs
divisibleBy3 n = mod n 3 == 0
now, your program can be written as
filter' divisibleBy3 inputList
I have just started learning Haskell and have written two functions, one for lists with even lengths and one for lists odd lengths. This means the 'even' function with [0..7] returns [0,7,2,5,4,3,6,1], and the 'odd' function with [0..8] returns [0,7,2,5,4,3,6,1,8] - these are the results I need.
However I after a lot of work I am still not able to combine them so that just one function works for both lists. Here are the functions and I wondered if more experienced Haskell coders know of a solution.
funcOdd :: [Int] -> [Int]
funcOdd [] = []
funcOdd (x:xs) = take (n+1) ((x*2) : (pred n - x):funcOdd(xs)) where n = length xs
funcEven :: [Int] -> [Int]
funcEven [] = []
funcEven (x:xs) = take (n+1) ((x*2) : (n - x):funcEven(xs)) where n = length xs
You can pattern match to separate the cases
fullFunction theList | even (length theList) = funcEven theList
fullFunction theList = funcOdd theList
when you call fullFunction, it will try the first case, checking if the length of the list is even. If this fails it will fallback to the second case.
Perhaps cleaner this way
func xs = zipWith const (go xs) xs
where go [] = []
go (x:xs) = 2*x : ((length xs)-off-x) : go xs
off = mod (length xs) 2
the only difference I see between the two functions is use of pred n vs n which is replaced with off(set) derived from the length of the original list.
zipWith const ... truncates the result with the length of the original list to replace take (n+1).
I try to learn how many elements are the same in the given two sets. To be clear,
let a = ["t","k","m"]
let b = ["k","b","t","c"]
"t" and "k" are parts of both lists, so the return will be 2. How can I implement like this function without using any library and using recursion?
You can use the module Data.Set to convert the two lists to sets and calculate the size of the intersection:
let a = Set.fromList ["t","k","m"]
let b = Set.fromList ["k","b","t","c"]
print $ Set.size (a `Set.intersection` b)
Live demo
As a general rule, if the order of the elements in the list doesn't matter and the list doesn't contain duplicates it's a good idea to convert it into a Set.
For some reason you don't want to use the standard library. If you don't care about algorithmic complexity you can then use:
length $ Prelude.filter (`elem` b) a
Live demo
of if you want it to be put into recursive form, then it's something like this:
countDuplicates :: (Eq a) => [a] -> [a] -> Int
countDuplicates [] b = 0
countDuplicates (x:rest) b =
let index = if x `elem` b then 1 else 0
in index + countDuplicates rest b
Live demo
which if you don't want to use elem either will be further expanded to:
countDuplicates :: (Eq a) => [a] -> [a] -> Int
countDuplicates [] b = 0
countDuplicates (x:rest) b =
let myElem a [] = False
myElem a (al:lst) = if a == al then True else myElem a lst
index = if x `myElem` b then 1 else 0
in index + countDuplicates rest b
Live demo
Without using any extra functions you can write it simply as follows
countIntersect :: (Eq a) => [a] -> [a] -> Int
countIntersect _ [] = 0
countIntersect [] _ = 0
countIntersect (x:xs) y'#(y:ys) | x==y = 1 + countIntersect xs ys
| otherwise = countIntersect [x] ys + countIntersect xs y'
essentially, the way you would do by hand, compare the first two elements if same increase the counter and move the next element in both list. If not equal compare the first element of the first list with the rest of second list and remainder of the first list to the second list.
I have a problem with a function that should only return the tail of a list. The functions is myTail and should give a useable result, even if the input is an empty list.
I want to understand all 3 ways: pattern matching, guarded equation and conditional expressions
this works:
> myTail_pat :: [a] -> [a]
> myTail_pat (x:xs) = xs
> myTail_pat [] = []
But this:
> myTail_guard (x:xs) | null xs = []
> | otherwise = xs
gives me the error: Program error: pattern match failure: myTail_guard []
How can i declare the function without patterns?
Thank you.
The pattern x:xs does not match the empty list. You'd need to do:
myTail_guard xs
| null xs = []
| otherwise = tail xs
drop 1 is safe
drop 1 []
-- result: []