Turn adjacency list into tuple array Haskell - list

Let's say I have the following input:
[(0, [1, 2]) , (2, [3, 4]) , (4, [])
This is an adjacency list and I want to convert it as such:
[(0,1), (0,2), (2,3), (2, 4)] -- notice how there is no 4 mapping to anything
Here is what I have so far:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv adj = map fn adj -- mapping (0, [1, 2]) should give me [(0, 1), (0, 2)]
fn:: (Int, [Int]) -> [(Int, Int)]
fn (rt, list) = -- somehow perform [(rt, l[0]), (rt, l[1]) ...]

List comprehension can do the trick:
conv :: [(a, [b])] -> [(a, b)]
conv xys = [(x, y) | (x, ys) <- xys, y <- ys ]
Or we can use concatMap here:
conv :: Foldable f => f (a, [b]) -> [(a, b)]
conv = concatMap (uncurry (map . (,)))
Here the inner function uncurry (map . (,)) takes a tuple (x, ys) and thus performs a map (x,): the uncurry basically unpacks the tuple (x, ys), and calls (map . (,)) x ys, so that means that we obtain (map (x,)) ys. The above syntax uses the TupleSections extension, but we do not need to activate that extension in the real program, since we never write such syntax. Your fn function you defined is thus equivalent to uncurry (map . (,)).
We thus use this function in a concatMap that will pass the 2-tuples, and concatenate the lists these individual tuples create.
or we can use the "bind" >>= :: Monad m => m a -> (a -> m b) -> m b function:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (\(x, ys) -> ys >>= return . (x,))
or shorter:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (uncurry (fmap . (,)))
the nice thing about the latter is that it also works with Maybes, etc. For example:
Prelude> conv [(0, [1, 2]) , (2, [3, 4]) , (4, [])]
[(0,1),(0,2),(2,3),(2,4)]
Prelude> conv Nothing
Nothing
Prelude> conv (Just (3, Nothing))
Nothing
Prelude> conv (Just (3, Just 2))
Just (3,2)

Taking advantage of instance Traversable ((,) a), we have this remarkably short (and remarkably inscrutable) solution:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv = (sequence =<<)
The most general type of (sequence =<<) is (Monad m, Traversable t) => m (t (m a)) -> m (t a).

Related

Haskell - separate a list of pairs in two lists using fold

So, I am given a list containing tuples and I need to break it down into two lists, the first list containing the elements with odd index and the second list containing the elements with even index, must be done using fold, here is my attempt:
breakList :: [(Integer, Integer)] -> [[(Integer, Integer)]]
breakList [] = [[], []]
breakList xxs#(x:xs) = foldl (\ acc y -> if length (acc !! 0) < length (acc !! 1) then y : (acc !! 0) else y : (acc !! 1) ) [[], []] xxs
Error I am getting:
Couldn't match type '(Integer, Integer)'
with '[(Integer, Integer)]'
Expected type: [[(Integer, Integer)]]
when hovering over y : (acc !! 1) and y : (acc !! 0)
Example:
Input:
ex1 = [ (2, 2), (1, 3), (2, 3), (2, 4), (3, 5), (0, 2), (2, 1), (1, 4)
, (2, 0), (1, 2), (3, 1), (1, 0)]
Output
breakList ex1
== ( [(2,2),(2,3),(3,5),(2,1),(2,0),(3,1)] , [(1,3),(2,4),(0,2),(1,4),(1,2),(1,0)])
The standard trick here, as hinted at by Willem in the comments, which I first saw few years back on SO in an (F# or Ocaml) answer by [user:Ed'ka], is
evenodds :: [a] -> ([a], [a])
evenodds xs = foldr g ([],[]) xs
where
g x ~(as,bs) = (bs,x:as)
or
oddevens :: [a] -> ([a], [a])
oddevens xs = foldr g ([],[]) xs
where
g x ~(bs,as) = (x:as,bs)
What are odd positions from here, are even positions from the position one notch further on the list.
The tilde ~ introduces a lazy pattern so that the function is properly lazy in its operations.
Note that you want to split a list into two lists of a pair, so the return type should be
([(Integer, Integer)], [(Integer, Integer)])
not
[[(Integer, Integer)]]
and access the element of pair, you can use fst and snd instead of through index, and finally, use foldl will return the resulted list in reversed order, it can be fixed use foldr instead. The correction look like:
breakList :: [(Integer, Integer)]->([(Integer, Integer)], [(Integer, Integer)])
breakList xxs = foldr (\y acc-> if length (fst acc) < length (snd acc)
then (y:(fst acc), snd acc)
else (fst acc, y:(snd acc)) ) ([], []) xxs

Combine a list of lists with a list using a function in Haskell

I want to be able to apply a function between each element of an input list and each element of each sublist in a list of lists like so:
mapFunc :: (a -> b -> c) -> [[a]] -> [b] -> [[c]]
For instance: mapFunc (*) [[1,2,3],[4,5,6]] [1,2,3] should give me: [[1,4,9],[4,10,18]].
Is there a specific way to do this in Haskell?
I know it probably requires a combination of zipWith and map in some manner and I have been trying them but not really been able to make any head way into my problem
I know it probably requires a combination of zipWith and map
You’re on the right track.
Given two lists xss and ys, you want to take each element of xss :: [[a]], being a list xs :: [a], and zip it with ys :: [b] using f :: a -> b -> c. “Each element” suggests map (or a list comprehension), so you can make a guess containing a “hole” which the compiler will report the type of:
mapFunc :: (a -> b -> c) -> [[a]] -> [b] -> [[c]]
mapFunc f xss ys = map (\xs -> _) xss
-- or,
mapFunc f xss ys = [_ | xs <- xss]
The type of this hole is [c] in either case; the compiler also gives us a list of things in scope that may be useful for filling the hole:
xs :: [a]
ys :: [b]
xss :: [[a]]
f :: a -> b -> c
mapFunc :: (a -> b -> c) -> [[a]] -> [b] -> [[c]]
Looking at the type of zipWith should then make it clear how to fill in this hole, i.e. how to construct a value with the type [c] by combining the values you have in scope:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
As an exercise, you can also manually inline the definitions of map and zipWith to understand how you would write this using manual recursion. A useful extension here is {-# LANGUAGE ScopedTypeVariables #-}, which allows you to define the scope of the types a, b, and c using a forall quantifier, so that you can break the problem down into local definitions and give type signatures for each part such that those type signatures could reuse the same type variables a, b and c. Try it yourself starting with this signature:
mapFunc :: forall a b c. (a -> b -> c) -> [[a]] -> [b] -> [[c]]
And if you get stuck, there’s a hint below for how I would structure a solution.
Fill in the blanks:
mapFunc :: forall a b c. (a -> b -> c) -> [[a]] -> [b] -> [[c]]
mapFunc f xss ys = mapping xss
where
mapping :: [[a]] -> [[c]]
mapping (xs : xss') = _
mapping [] = _
zipping :: [a] -> [b] -> [c]
zipping (x : xs) (y : ys) = _
zipping [] _ = _
zipping _ [] = _
So we must have
mapFunc (*) [[1,2,3], [4, 5, 6]] [1,2,3]
== [[1,4,9], [4,10,18]]
and so, also
mapFunc (*) [[1,2,3], [4, 5, 6], [7, 8, 9, 10]] [1,2,3]
== [[1,4,9], [4,10,18], [7, 14, 27] ]
-- and
mapFunc (*) [[1,2,3]] [1,2,3]
== [[1,4,9]]
-- and
mapFunc (*) [[4, 5, 6], [7, 8, 9, 10]] [1,2,3]
== [[4,10,18], [7, 14, 27] ]
Thus,
mapFunc (*) ([[1,2,3]] ++ [[4, 5, 6], [7, 8, 9, 10]]) [1,2,3]
== (mapFunc (*)
[[1,2,3]] [1,2,3])
++
(mapFunc (*) [[4, 5, 6], [7, 8, 9, 10]] [1,2,3])
There's nothing special about these specific numbers though, so we must necessarily have
mapFunc (*) ( [xs] ++ xss ) ys =
= (mapFunc (*) [xs] ys ++ mapFunc (*) xss ys)
= ([g xs ys] ++ mapFunc (*) xss ys)
because as we see from our examples, (\xss -> mapFunc (*) xss ys) is a length-preserving transformation.
So what should this g function be?
Lather, rinse, repeat:
We must have
g [1,2,3] [1,2,3] == [1,4,9]
g [4,5,6] [1,2,3] == [4,10,18]
g [7,8,9,10] [1,2,3] == [7,14,27]
and thus, again generalizing as the numbers are nothing special in themselves,
g xs ys = [ (*) x y | x <- xs | y <- ys ]
and that's that.

Combining three lists into a list of 3-tuples in Haskell

I am trying to write a function that takes three lists as arguments and creates one list with a triple from each list consecutively.
The example I was given is this: zip3Lists [1, 2, 3] [4, 5, 6] ['a', 'b', 'c'] would produce [(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')].
What I have so far is this:
zipThree [] [] [] = []
zipThree [] [] [x] = [x]
zipThree [] [x] [] = [x]
zipThree [x] [] [] = [x]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
and it is giving me this error:
haskell1.hs:32:33: error:
• Occurs check: cannot construct the infinite type: c ~ (c, c, c)
Expected type: [c]
Actual type: [(c, c, c)]
• In the expression: (x, y, z) : zipThree xs ys zs
In an equation for ‘zipThree’:
zipThree (x : xs) (y : ys) (z : zs) = (x, y, z) : zipThree xs ys zs
• Relevant bindings include
zs :: [c] (bound at haskell1.hs:32:27)
z :: c (bound at haskell1.hs:32:25)
ys :: [c] (bound at haskell1.hs:32:20)
y :: c (bound at haskell1.hs:32:18)
xs :: [c] (bound at haskell1.hs:32:13)
x :: c (bound at haskell1.hs:32:11)
(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)
First of all let's add a type signature. From the question it seems as if the following type signature is appropriate:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
This takes 3 lists (containing possibly different types of objects) and then produces a list of triples.
You handle the empty list case fine:
zipThree [] [] [] = []
Then the problem occurs. As stated in the comments you have cases for the lists having different lengths but that give a different type of output.
I'll annotate the types next to each line so you can see:
zipThree [] [] [x] = [x] :: [c]
zipThree [] [x] [] = [x] :: [b]
zipThree [x] [] [] = [x] :: [a]
These don't fit with the other two cases that have type [(a, b, c)].
You mentioned in the comments that you will just presume the lengths are the same size therefore just removing these cases is sufficient. This gives:
zipThree [] [] [] = []
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
Which provides the correct output ([(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')]) for the input you gave ([1, 2, 3] [4, 5, 6] ['a', 'b', 'c']).
This function of course will fail on inputs where the lists are of different lengths. One way to stop a straight up error and allow you to handle the issue would be to wrap the result in a Maybe.
First we need to change the type to:
zipThree :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
The Maybe data type can either be a value wrapped in Just so Just a or Nothing.
For the empty list we want to give just the empty list:
zipThree [] [] [] = Just [].
Naturally you might think that the next case should be:
zipThree (x:xs) (y:ys) (z:zs) = Just $ (x, y, z) : zipThree xs ys zs.
But this doesn't work. Don't forget zipThree xs ys zs now has type Maybe [(a, b, c)] whereas (x, y, z) has type (a, b, c) so we can't add it to the list.
What we need to do is check the result of zipThree xs ys zs if it failed at some point during the recursion then it will be Nothing so we just want to pass that Nothing along again. If it succeeded and gave us Just as then we want to add our (x, y, z) to that list. We can check which case is relevant using case of:
zipThree (x:xs) (y:ys) (z:zs) = case zipThree xs ys zs of
Nothing -> Nothing
Just as -> Just $ (x, y, z) : as
We will know our lists aren't the same length if at some point during the recursion some lists are empty and others aren't. This doesn't match either pattern we have at the moment [] [] [] or (x:xs) (y:ys) (z:zs) so we need one final catch all case to give us that Nothing and prevent the error:
zipThree _ _ _ = Nothing
This gives a final definition of:
zipThree :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
zipThree [] [] [] = Just []
zipThree (x:xs) (y:ys) (z:zs) = case zipThree xs ys zs of
Nothing -> Nothing
Just as -> Just $ (x, y, z) : as
zipThree _ _ _ = Nothing
The results for the examples are:
zipThree [1, 2, 3] [4, 5, 6] ['a', 'b', 'c', 'd'] = Nothing
and
zipThree [1, 2, 3] [4, 5, 6] ['a', 'b', 'c'] = Just [(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')].
Hope this helps, feel free to ask for clarification :)
EDIT: As suggested in the comments the following definitions would stop short in the case the lists are different lengths:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
zipThree _ _ _ = []
zipThree :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = case zipThree xs ys zs of
Nothing -> Just [(x, y, z)] -- Change is here
Just as -> Just $ (x, y, z) : as
zipThree _ _ _ = Nothing
P.S. Thanks to the guy who added the missing Just in an edit.
There is this ZipList type defined in Control.Applicative module which is in fact exactly thought for this job.
ZipList type is derived from the List type like
newtype ZipList a = ZipList { getZipList :: [a] }
deriving ( Show, Eq, Ord, Read, Functor, Foldable
, Generic, Generic1)
Unlike normal Lists it's Applicative instance does not work on combinations but one to one on corresponding elements like zipping. Hence the name ZipList. This is the Applicative instance of ZipList
instance Applicative ZipList where
pure x = ZipList (repeat x)
liftA2 f (ZipList xs) (ZipList ys) = ZipList (zipWith f xs ys)
The advantage of zipList is we chain up indefinitely many lists to zip with. So when zipWith7 is not sufficient you may still carry on with a ZipList. So here is the code;
import Control.Applicative
zip'mAll :: [Int] -> [Int] -> String -> [(Int,Int,Char)]
zip'mAll xs ys cs = getZipList $ (,,) <$> ZipList xs <*> ZipList ys <*> ZipList cs
*Main> zip'mAll [1,2,3] [4,5,6] "abc"
[(1,4,'a'),(2,5,'b'),(3,6,'c')]
Firstly, we need a type signature, as stated by James Burton, who lists a suitable one also:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
Essentially, this type signature says that, given three lists of any type a, b or c, a list of three-value tuples whose type is (a, b, c) shall be produced.
If we disregard the need to handle invalid cases (empty lists, variable-length lists), we next need to implement a valid case which produces the correct tuple from the lists given. Your statement
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
is valid. Therefore, thus far we have:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
The problem occurs when you introduce the cases for your invalid lists:
zipThree [] [] [x] = [x]
zipThree [] [x] [] = [x]
zipThree [x] [] [] = [x]
When one of these cases is matched, the type attempting to be bound is invalid due to being of type [x], where type (x, y, z) is expected.
You could exhaustively attempt to match base cases before recursively accessing the function again. However, you could also simply declare the case
zipThree _ _ _ = []
after, which will end the recursion with invalid input.
Putting this altogether, we are left with:
zipThree :: [a] -> [b] -> [c] -> [(a, b, c)]
zipThree (x:xs) (y:ys) (z:zs) = (x, y, z) : zipThree xs ys zs
zipThree _ _ _ = []
What's good about this implementation is that the recursion ends when any list is empty, thus stopping short for uneven lists, e.g.
zipThree [1, 2, 3] [4, 5, 6] [7, 8]
would produce
[(1, 4, 7), (2, 5, 8)]
Good luck!

Nested chunksOf in Haskell?

Say I want to do this:
nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4] == [[[1,1,1], [2,2,2]], [[3,3,3], [4,4,4]]]
In Python, I can do this
def group(a, *ns):
for n in ns:
a = [a[i:i+n] for i in xrange(0, len(a), n)]
return a
group([1,1,1,2,2,2,3,3,3,4,4,4], 3, 2) == [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
But in Haskell, I can't just say
nestedChunksOf :: [Int] -> [a] -> [[a]]
or
nestedChunksOf :: [Int] -> [a] -> [[[a]]]
So how can I achieve the same thing in Haskell?
A function like nestedChunksOf can't be done directly in Haskell, at least not one which operates on normal lists. The depth of the list is part of the type, so you can't have an arbitrary depth specified by a parameter.
But what you can do is nest chunksOf.
If we define chunksOf like this:
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs = fxs : chunksOf n sxs
where (fxs, sxs) = splitAt n xs
We can then nest it:
Main> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[1,1,1],[2,2,2],[3,3,3],[4,4,4]]
*Main> chunksOf 2 $ chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
I hope that accomplishes what you wanted!
As stated in the other answers, this can't be done directly as in Haskell you always need to know the type of an expression and thus distinguish between [a], [[a]] etc. However, using polymorphic recursion you can define a data type that allows such arbitrary nesting by wrapping each level in a constructor:
data NestedList a = Value a | Nested (NestedList [a])
deriving (Show)
So just Value is isomorphic to a, Nested (Value ...) is isomorphic to [a], double Nested to [[a]] etc. Then you can implement
chunksOf :: Int -> [a] -> [[a]]
...
nestedChunksOf :: [Int] -> [a] -> NestedList a
nestedChunksOf [] xs = Nested (Value xs)
nestedChunksOf (c:cs) xs = Nested (nestedChunksOf cs $ chunksOf c xs)
And indeed
print $ nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4]
outputs
Nested (Nested (Nested (Value [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]])))
It can be done fairly easily with dependent types.
We'd like to express that the length of the [Int] argument determines the type of the result. We need two things for that: a list type with fixed length, and a type-level function which computes the return type from the length:
{-# LANGUAGE DataKinds, GADTs, TypeFamilies #-}
import Data.List.Split
data Nat = Z | S Nat -- natural numbers (zero, successor)
data Vec n a where -- "n" length lists of "a" elements
Nil :: Vec Z a
(:>) :: a -> Vec n a -> Vec (S n) a
infixr 5 :>
type family Iterate n f a where
Iterate Z f a = a
Iterate (S n) f a = f (Iterate n f a)
Iterate n f a applies the type constructor f n times to an argument. For example, Iterate (S (S Z)) [] Int reduces to [[Int]]. nestedChunksOf can be written directly now:
nestedChunksOf :: Vec n Int -> [a] -> Iterate (S n) [] a
nestedChunksOf Nil as = as
nestedChunksOf (n :> ns) as = chunksOf n $ nestedChunksOf ns as
Usage:
> nestedChunksOf (2 :> 3 :> Nil) [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
This can not be achieved in Haskell through "normal" means because it would require a dependent type - the type of the result depends on the length of the first argument.
Perhaps a tuple solution would be acceptable?
{-# Language TypeFamilies #-}
{-# Language FlexibleInstances #-}
import Data.List.Split
class NestedChunksOf a where
nco :: a -> [b] -> AList a b
type AList a b :: *
instance NestedChunksOf (Int,Int) where
nco (f,s) xs = chunksOf f (chunksOf s xs)
type AList (Int,Int) a = [[[a]]]
-- More instances as desired.

haskell, is number in one list is within the range of a second list?

What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]