I have a list as List<List<String>> next = iterator.next(); In this list data will be like
[[a, b, c], [a, b]]
[[a, b, c], [a]]
[[a, b], [a]]
When I convert into a list as,
List<String> collect = list.stream().flatMap(List::stream).collect(Collectors.toList());
it returns a list like,
[a, b, c, a, b]
[a, b, c, a]
[a, b, a]
Is there a possible way to create a new List<String> using List<List<String>> as same as,
[[a, b, c], [a, b]]
[[a, b, c], [a]]
[[a, b], [a]]
What you seem to intend is just use List.toString as:
List<String> collect = list.stream()
.map(Object::toString) // default string representation for the inner list
.collect(Collectors.toList());
Related
I am attempting to write a function called that takes a list of triples and produces a 3-tuple of three lists. For instance, the function called on [(a,b,c), (d, e, f), (g, h, i)] should produce ([a,d,g], [b, e, j], [c, f, i]).
I have this so far:
-- This gives the head of a 3-tuple
fst3 :: (a, b, c) -> a
fst3 (x, _, _) = x
unzipTriples :: [(a, b, c)] -> a
unzipTriples (x : y : z : xs) = (fst3 x : fst3 y : fst3 z, unzipTriples xs)
I thought this would create a list [a, d, g] and then add it to the 3-tuple and do the rest for the remaining list. How can I improve this wrong function?
The pattern (x : y : z : xs) in unzipTriples (x : y : z : xs) = … will take the first three elements of the list, so then x, y and z are 3-tuples. But you thus would limit yourself to processing lists with three or more elements.
What you can do is use map and thus work with:
fst3 :: (a, b, c) -> a
fst3 (a, _, _) = a
snd3 :: (a, b, c) -> b
snd3 (_, b, _) = b
thd3 :: (a, b, c) -> c
thd3 (_, _, c) = c
unzipTriples :: [(a, b, c)] -> ([a], [b], [c])
unzipTriples xs = (map fst3 xs, map snd3 xs, map thd3 xs)
But it is probably more elegant, and will consume less memory when you pattern match on the first item of the list, a 3-tuple, and then recurse on the tail of the list, so:
unzipTriples :: [(a, b, c)] -> ([a], [b], [c])
unzipTriples [] = ([], [], [])
unzipTriples ((a, b, c):xs) = (a:as, b:bs, c:cs)
where ~(as, bs, cs) = unzipTriples xs
You can convert this into an expression with foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b, I leave this as an exercise.
I am new in Haskell. Can anyone explain the difference and the usage of Ord a?
Now I'm familiar with [a] -> [a] -> [a] things. But this,
Ord a => [a] -> [a] -> [a]
please explain me in detail.
The difference is in the constraint, Ord a => a here a has type a but not any a, an a that is an instance of Ord typeclass, example:
here I will change a little bit the type result only to show you can use the functions of the interface:
canBeOrderedList :: Ord a => [a] -> [a] -> [Bool]
canBeOrderedList xs ys = zipWith (>) xs ys
here you can do whatever generic function you want, a here is not restricted, so it can be Ord or Eq or both or none, can be functions, can be Ints can be anything
anyListTypeConcat :: [a] -> [a] -> [a]
anyListTypeConcat xs ys = xs ++ ys
so:
anyListTypeConcat [True, False] [False, True]
=> [True,False,False,True]
here you concatted the two list, so far so good, here:
canBeOrderedList [1,2,3] [4,1,2]
=> [False,True,True]
you can use (>) with numbers but, what about:
data Some = A | B | C deriving (Eq, Show)
anyListTypeConcat [A, A] [B, C]
=> [A,A,B,C]
but:
canBeOrderedList [A,A,B] [C,A,A]
error:
• No instance for (Ord Some)
arising from a use of ‘canBeOrderedList’
• In the expression: canBeOrderedList [A, A, B] [C, A, A]
In an equation for ‘it’: it = canBeOrderedList [A, A, B] [C, A, A]
You cannot order that list, but you may if you change the data type:
data Some = A | B | C deriving (Eq, Show, Ord)
canBeOrderedList [A,A,B] [C,A,A]
=> [False,False,True]
And that's essentially the difference
Consider:
-- merge :: [a] -> [a] -> [a] ?
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| y < x = y : merge (x:xs) ys
| otherwise = x : merge xs (y:ys)
In particular, look at the second-to-last line. See that (<) operator?
ghci> :i (<)
class Eq a => Ord a where
...
(<) :: a -> a -> Bool
We can see here that the less-than operator does not exist for type not of class Ord; that merge function therefore makes no sense unless we have Ord a. We therefore rewrite its type signature as:
merge :: Ord a => [a] -> [a] -> [a]
I have a list of function, e.g [f g h ..] and list items with the same length [a b c ..].
What's proper way to get result as: [(f a) (g b) (h c) ..] (apply each function to an item at the same position)
How do I accumulate the successive application of a function to a list of values in Haskell?
I'm not sure I'm phrasing that right, but what I'm looking for, for example, is that I have a list values of type X,
l = [a, b, c, d, e]
and a function
f :: X -> X -> X
and I want
(f e (f d (f c (f b a))))
which I think can perhaps be expressed with $ somehow.
I see that Haskell has some fold functions, but I can't quite figure out how to get it to work like the fold operations I'm familiar with.
Isn't this just foldl1 (flip f) l? You want a left fold, and you want the operation to start with the first item in the list rather than a specific accumulator.
Well, your function f really has type:
f :: X -> X -> X
Then the expression you are interested in is:
foldr1 f [e, d, c, a, b] -- note the twist at the end.
If you want to compute:
f e (f d (f c (f b a))) -- note last term is: f b a
then it is just:
foldr1 f [e, d, c, b, a]
Play with simple-reflect to figure it out.
ghci> import Debug.SimpleReflect
ghci> foldl1 f [a,b,c,d,e]
f (f (f (f a b) c) d) e
ghci> foldl (flip f) z [a,b,c,d,e]
f e (f d (f c (f b (f a z))))
And so on...
I have this simple list structure where every leaf holds two values (a and b) and every node holds one value (a)
data List a b = Leaf (a, b) | Node (a, (List a b)) deriving Show
And I have this function just returning the value of a node or the first value of a leaf
func (Leaf (a, b)) = a
func (Node (a, c)) = a
Is there a way avoid one of these pattern matches? In fact I'm working on a ternary-tree and functions which have more than one argument, so I have a lot of pattern matches which are all doing the same thing.
I thought about something like this
func (var (a, b)) = a
where var can be a leaf or a node, but this does not work.
If you're comfortable with it, you can refactor your type as:
data List a b = L (a, Either b (List a b)) deriving Show
Then,
func :: List a b -> a
func (L (a,_)) = a
Previous values like
Leaf (a, b)
Node (a, list)
are now written as
L (a, Left b)
L (a, Right list)
Depending on your code, this might be more convenient to use.
However, keep in mind that if you need to access the second component of the pair, you need to pattern match anyway. It is likely that your current datatype is more convenient, overall, than this alternative.
I "solved" it by adding a help function returning the first value
gf (Leaf (a, b)) = a
gf (Node (a, b)) = a
So I can always use this function
func x = gf x
There are still two pattern matches but in case of more complex functions expecting more than one argument it is useful to avoid a lot of pattern matches
i.e
addValues (Leaf (a, b)) (Leaf (c, d)) (Leaf (e, f)) = a + c + e
addValues (Leaf (a, b)) (Leaf (c, d)) (Node (e, f)) = a + c + e
addValues (Leaf (a, b)) (Node (c, d)) (Leaf (e, f)) = a + c + e
addValues (Leaf (a, b)) (Node (c, d)) (Node (e, f)) = a + c + e
addValues (Node (a, b)) (Leaf (c, d)) (Leaf (e, f)) = a + c + e
addValues (Node (a, b)) (Leaf (c, d)) (Node (e, f)) = a + c + e
addValues (Node (a, b)) (Node (c, d)) (Leaf (e, f)) = a + c + e
addValues (Node (a, b)) (Node (c, d)) (Node (e, f)) = a + c + e
can now be written as
addValues (a, b, c) = (gf a) + (gf b) + (gf c)