I am new in haskell and I have a problem (aka homework).
So, I have a list with a tuple – a string and an integer:
xxs :: [([Char], Integer)]
I need to know how many of the strings in xxs start with a given character.
Let me exemplify:
foo 'A' [("Abc",12),("Axx",34),("Zab",56)]
Output: 2
foo 'B' [("Abc",12),("Bxx",34),("Zab",56)]
Output: 1
My best attempt so far:
foo c xxs = length (foldl (\acc (x:xs) -> if x == c then c else x) [] xxs)
But, of course, there's something VERY wrong inside the lambda expression.
Any suggestion?
Thanks.
You can use a fold, but I would suggest another way, which breaks the problem in three steps:
transform the input list to the list of first letters. You can use map for this
filter out all elements not equal to the given Char
take the length of the remaining list
Obviously the first step is the hardest, but not as hard as it looks. For doing it you just have to combine somehow the functions fst and head, or even easier, map twice.
You can write this as a simple one-liner, but maybe you should start with a let:
foo c xxs = let strings = map ...
firstLetters = map ...
filteredLetters = filter ...
in length ...
There are a few problems with your attempt:
You plan to use foldl to construct a shorter list and then to take its length. While it is possible, filter function is much better suited for that task as #landei suggests
foldl can be used to accumulate the length without constructing a shorter list. See the answer of #WuXingbo - his answer is incorrect, but once you realize that length is not needed at all with his approach, it should be easy for you to come with correct solution.
Somewhat contradictory to common sense, in a lazy language foldr is faster and uses less memory than foldl. You should ask your teacher why.
I would rewrite foo as
foo :: Char -> [(String, Int)] -> Int
foo c = length . filter ((==c).head.fst)
fst fetches the first element of a two-element tuple.
(==c) is a one-argument function that compares its input with c (see http://www.haskell.org/tutorial/functions.html paragraph 3.2.1 for better explanation).
Related
I want to input two strings, "Hello" and "Hi" for example, and I want to go through every element in the two strings simultaneously and compare every character one by one. The two strings length in the actual program should be 5, if a char is equal to the other, return true, otherwise return false.
The program I have in mind should see 'H' in "Hello" and 'H' from "Hi" and return true, then I want it to check the 'e' in "Hello" and the 'i' in "Hi" and return false. I want it to keep on doing that till there is nothing to compare. I think I might need to use recursion but I am not sure how to implement it in this program really.
I tried using x:xs with the maximum range of 5 so [0..5], but it didn't work at all.
My code (not working):
uncurryingString :: String -> Int -> Char
uncurryingString a b = a !! b
match :: String -> String -> [Int] -> Bool
match a b (x:xs)
| uncurryingString a [x+1 | x <- xs] == uncurryingString b [x+1 | x <- xs] = True
| otherwise = False
You're thinking about this way too complicated.
First, as a rule of thumb, you should never use !! (whether directly or via some helper – uncurryingString is in fact exactly the same as !! itself). If direct indexing is required, a list is not the right data structure. But very often direct indexing is not required, it's just what's customarily used in some other programming languages that don't have pattern matching to do it more elegantly.
In your application, you're deconstructing both strings in parallel. Well, you should express that with a pattern match:
match (a:as) (b:bs) (x:xs) = ...
And now you can simply compare a and b directly, no need for messing about with any list comprehensions or indexing operators. In the example input "Hello" and "Hi", both a and b will be 'H' here.
But you probably don't want to return True right there, because there's still the rest of the string to be matched. That's where recursion comes in.
Finally, you need to clauses in case not all of the input lists are nonempty. Try to figure that out yourself.
What you probably don't need at all is the extra [Int] argument (x:xs). It could make sense to have a depth-limiting argument, but that could be simply an Int. You would then do something like
match :: Eq a => [a] -> [a] -> Int -> Bool
match _ _ 0 = True -- lists are equal up to the specified max depth
match (a:as) (b:bs) n = ...
...
Using a list comprehension is often a good way to compute things in Haskell, but not in this particular case.
I could try this code:
[a==b | a <- "Hello", b <- "Hi"]
What does this do? You might think that this returns True, because the 'H' letters match - or you might thing that this returns False, because the other letters don't match. In fact, it does both - in effect, it is running multiple nested loops.
[True,False,False,False,False,False,False,False,False,False]
So, the takeaway is to use list comprehensions when you want nested loops, or just working through one dataset. Here we just want a single loop that works through the two words in parallel. Hence it must be recursion.
Doing the third of the 99-Haskell problems (I am currently trying to learn the language) I tried to incorporate pattern matching as well as recursion into my function which now looks like this:
myElementAt :: [a] -> Int -> a
myElementAt (x ++ xs) i =
if length (x ++ xs) == i && length xs == 1 then xs!!0
else myElementAt x i
Which gives me Parse error in pattern: x ++ xs. The questions:
Why does this give me a parse error? Is it because Haskell is no idea where to cut my list (Which is my best guess)?
How could I reframe my function so that it works? The algorithmic idea is to check wether the list has the length as the specified inde; if yes return the last elemen; if not cut away one element at the end of the list and then do the recursion.
Note: I know that this is a really bad algorithm, but it I've set myself the challenge to write that function including recursion and pattern matching. I also tried not to use the !! operator, but that is fine for me since the only thing it really does (or should do if it compiled) is to convert a one-element list into that element.
Haskell has two different kinds of value-level entities: variables (this also includes functions, infix operators like ++ etc.) and constructors. Both can be used in expressions, but only constructors can also be used in patterns.
In either case, it's easy to tell whether you're dealing with a variable or constructor: a constructor always starts with an uppercase letter (e.g. Nothing, True or StateT) or, if it's an infix, with a colon (:, :+). Everything else is a variable. Fundamentally, the difference is that a constructor is always a unique, immediately matcheable value from a predefined collection (namely, the alternatives of a data definition), whereas a variable can just have any value, and often it's in principle not possible to uniquely distinguish different variables, in particular if they have a function type.
Yours is actually a good example for this: for the pattern match x ++ xs to make sense, there would have to be one unique way in which the input list could be written in the form x ++ xs. Well, but for, say [0,1,2,3], there are multiple different ways in which this can be done:
[] ++[0,1,2,3]
[0] ++ [1,2,3]
[0,1] ++ [2,3]
[0,1,2] ++ [3]
[0,1,2,3]++ []
Which one should the runtime choose?
Presumably, you're trying to match the head and tail part of a list. Let's step through it:
myElementAt (x:_) 0 = x
This means that if the head is x, the tail is something, and the index is 0, return the head. Note that your x ++ x is a concatenation of two lists, not the head and tail parts.
Then you can have
myElementAt(_:tl) i = myElementAt tl (i - 1)
which means that if the previous pattern was not matched, ignore the head, and take the i - 1 element of the tail.
In patterns, you can only use constructors like : and []. The append operator (++) is a non-constructor function.
So, try something like:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = ...
There are more issues in your code, but at least this fixes your first problem.
in standard Haskell pattern matches like this :
f :: Int -> Int
f (g n 1) = n
g :: Int -> Int -> Int
g a b = a+b
Are illegal because function calls aren't allowed in patterns, your case is just a special case as the operator ++ is just a function.
To pattern match on lists you can do it like this:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = // result
But in this case x is of type a not [a] , it is the head of the list and xs is its tail, you'll need to change your function implementation to accommodate this fact, also this function will fail with the empty list []. However that's the idiomatic haskell way to pattern match aginst lists.
I should mention that when I said "illegal" I meant in standard Haskell, there are GHC extensions that give something similar to that , it's called ViewPatterns But I don't think you need it especially that you're still learning.
I want to see how long a list is, but without using the function length. I wrote this program and it does not work. Maybe you can tell me why? Thanks!
let y = 0
main = do
list (x:xs) = list (xs)
y++
list :: [Integer] -> Integer
list [] = y
Your program looks quite "imperative": you define a variable y, and then somehow write a do, that calls (?) the list function (?) that automagically seems to "return y" and then you want to increment y.
That's not how Haskell (and most functional and declarative) languages work:
in a declarative language, you define a variable only once, after the value is set, there is usually no way to alter its value,
in Haskell a do usually is used for monads, whereas the length is a pure function,
the let is a syntax construction to define a variable within the scope of an expression,
...
In order to program Haskell (or any functional language), you need to "think functional": think how you would solve the problem in a mathematical way using only functions.
In mathematics, you would say that the empty list [] clearly has length 0. Furthermore in case the list is not empty, there is a first element (the "head") and remaining elements (the "tail"). In that case the result is one plus the length of the tail. We can convert that in a mathematical expression, like:
Now we can easily translate that function into the following Haskell code:
ownLength :: [a] -> Int
ownLength [] = 0
ownLength (_:xs) = 1 + ownLength xs
Now in Haskell, one usually also uses accumulators in order to perform tail recursion: you pass a parameter through the recursive calls and each time you update the variable. When you reach the end of your recursion, you return - sometimes after some post-processing - the accumulator.
In this case the accumulator would be the so far seen length, so you could write:
ownLength :: [a] -> Int
ownLength = ownLength' 0
where ownLength' a [] = a
ownLength' a (_:xs) = ownLength' (a+1) xs
It looks you still think in an imperative way (not the functional way). For example:
you try to change the value of a "variable" (i.e. y++)
you try to use "global variable" (i.e. y) in the body of the list function
Here is the possible solution to your problem:
main = print $ my_length [1..10]
my_length :: [Integer] -> Integer
my_length [] = 0
my_length (_:xs) = 1 + my_length xs
You can also run this code here: http://ideone.com/mjUwL9.
Please also note that there is no need to require that your list consists of Integer values. In fact, you can create much more "agnostic" version of your function by using the following declaration:
my_length :: [a] -> Integer
Implementation of this function doesn't rely on the type of items from the list, thus you can use it for a list of any type. In contrast, you couldn't be that much liberal for, for example, my_sum function (a potential function that calculates the sum of elements from the given list). In this situation, you should define that your list consists of some numerical type items.
At the end, I'd like to suggest you a fantastic book about Haskell programming: http://learnyouahaskell.com/chapters.
Other answers have already beautifully explained the proper functional approach. It looks like an overkill but here is another way of implementing the length function by using only available higher order functions.
my_length :: [a] -> Integer
my_length = foldr (flip $ const . (+1)) 0
I've found this solution in Learn you a haskell.
length' xs = sum [1 | _ <- xs]
It replaces every element of the list with 1 and sums it up.
Probably the simplest way is to convert all elements to 1 and then to sum the new elements:
sum . map (const 1)
For added speed:
foldl' (+) 0 . map (const 1)
I want to get the first element of every tuple stored in a list like so:
INPUT : [(1,2,3), (1,4,5), (1,6,7)]
Wanted OUTPUT : [(1,1,1)] % Note the tuple notation
This is the function I have written so far:
f [] = []
f ((x,y,z):xs) = x:(f xs)
But it gives me this output:
[1,1,1]
instead of
[(1,1,1)]
Where is my misunderstanding?
As yet stated in the comment by #pdexter, you cannot create a tuple with arbitrary length. So what you're trying to do will only work when the tuple exactly pattern matches a tuple with 3 Ints. Let me show you an example to clarify what I mean:
helper :: [(Int,Int,Int)] -> (Int,Int,Int)
helper xs = (x,y,z)
where [x,y,z] = f xs
f :: [(Int,Int,Int)] -> [Int]
f [] = []
f ((x,y,z):xs) = x : (f xs)
Here we manage to create (x,y,z) by pattern matching on [x,y,z], but what if there were more than three tuples, our pattern matching would no longer be valid?
So you should ask yourself the question what it is you're really trying to accomplish with this code and what scenarios might occur (e.g.: empty tuples, tuples with varying lengths mutually, .. ?) and also, how should your program handle these different cases?
If there is no functional reason as to why you like the output to be in a tuple, I suggest you keep the function as is.
Good luck!
So, I'm new here, and I would like to ask 2 questions about some code:
Duplicate each element in list by n times. For example, duplicate [1,2,3] should give [1,2,2,3,3,3]
duplicate1 xs = x*x ++ duplicate1 xs
What is wrong in here?
Take positive numbers from list and find the minimum positive subtraction. For example, [-2,-1,0,1,3] should give 1 because (1-0) is the lowest difference above 0.
For your first part, there are a few issues: you forgot the pattern in the first argument, you are trying to square the first element rather than replicate it, and there is no second case to end your recursion (it will crash). To help, here is a type signature:
replicate :: Int -> a -> [a]
For your second part, if it has been covered in your course, you could try a list comprehension to get all differences of the numbers, and then you can apply the minimum function. If you don't know list comprehensions, you can do something similar with concatMap.
Don't forget that you can check functions on http://www.haskell.org/hoogle/ (Hoogle) or similar search engines.
Tell me if you need a more thorough answer.
To your first question:
Use pattern matching. You can write something like duplicate (x:xs). This will deconstruct the first cell of the parameter list. If the list is empty, the next pattern is tried:
duplicate (x:xs) = ... -- list is not empty
duplicate [] = ... -- list is empty
the function replicate n x creates a list, that contains n items x. For instance replicate 3 'a' yields `['a','a','a'].
Use recursion. To understand, how recursion works, it is important to understand the concept of recursion first ;)
1)
dupe :: [Int] -> [Int]
dupe l = concat [replicate i i | i<-l]
Theres a few problems with yours, one being that you are squaring each term, not creating a new list. In addition, your pattern matching is off and you would create am infinite recursion. Note how you recurse on the exact same list as was input. I think you mean something along the lines of duplicate1 (x:xs) = (replicate x x) ++ duplicate1 xs and that would be fine, so long as you write a proper base case as well.
2)
This is pretty straight forward from your problem description, but probably not too efficient. First filters out negatives, thewn checks out all subtractions with non-negative results. Answer is the minumum of these
p2 l = let l2 = filter (\x -> x >= 0) l
in minimum [i-j | i<-l2, j<-l2, i >= j]
Problem here is that it will allow a number to be checkeed against itself, whichwiull lend to answers of always zero. Any ideas? I'd like to leave it to you, commenter has a point abou t spoon-feeding.
1) You can use the fact that list is a monad:
dup = (=<<) (\x -> replicate x x)
Or in do-notation:
dup xs = do x <- xs; replicate x x; return x
2) For getting only the positive numbers from a list, you can use filter:
filter (>= 0) [1,-1,0,-5,3]
-- [1,0,3]
To get all possible "pairings" you can use either monads or applicative functors:
import Control.Applicative
(,) <$> [1,2,3] <*> [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
Of course instead of creating pairs you can generate directly differences when replacing (,) by (-). Now you need to filter again, discarding all zero or negative differences. Then you only need to find the minimum of the list, but I think you can guess the name of that function.
Here, this should do the trick:
dup [] = []
dup (x:xs) = (replicate x x) ++ (dup xs)
We define dup recursively: for empty list it is just an empty list, for a non empty list, it is a list in which the first x elements are equal to x (the head of the initial list), and the rest is the list generated by recursively applying the dup function. It is easy to prove the correctness of this solution by induction (do it as an exercise).
Now, lets analyze your initial solution:
duplicate1 xs = x*x ++ duplicate1 xs
The first mistake: you did not define the list pattern properly. According to your definition, the function has just one argument - xs. To achieve the desired effect, you should use the correct pattern for matching the list's head and tail (x:xs, see my previous example). Read up on pattern matching.
But that's not all. Second mistake: x*x is actually x squared, not a list of two values. Which brings us to the third mistake: ++ expects both of its operands to be lists of values of the same type. While in your code, you're trying to apply ++ to two values of types Int and [Int].
As for the second task, the solution has already been given.
HTH