Related
I am attempting to understand how to use zip in Haskell. I've been learning Haskell recently and am trying to create a list of tuples from two separate lists
I have the following:
createList :: [Char] -> [Char] -> [(Char,Char)]
createList xs ys = zip(xs,ys)
I understand zip is supposed to create a list of tuples given two lists, but I get the following error:
Couldn't match expected type ‘[a0]’
with actual type ‘([Char], [Char])’
Can anyone explain to me where I am stumbling?
Haskell function calls don't use brackets or commas.
You can write the createList function as:
createList xs ys = zip xs ys
or simply
createList = zip
Thus, the createList function is redundant; it's just zip. The only potential use for the alias that I can think of is if you truly want to constrain the type as given.
If you remove the parenthesis around zip call, your code should work:
createList :: [Char] -> [Char] -> [(Char,Char)]
createList xs ys = zip xs ys
Explanation:
Full error I am getting when I run zip ([1, 2, 3], [4, 5, 6]) (notice the parens):
<interactive>:4:5:
Couldn't match expected type ‘[a]’
with actual type ‘([Integer], [Integer])’
Relevant bindings include
it :: [b] -> [(a, b)] (bound at <interactive>:4:1)
In the first argument of ‘zip’, namely ‘([1, 2, 3], [4, 5, 6])’
In the expression: zip ([1, 2, 3], [4, 5, 6])
In an equation for ‘it’: it = zip ([1, 2, 3], [4, 5, 6])
Notice the part that says In the first argument of ‘zip’, namely ‘([1, 2, 3], [4, 5, 6])’. The parens are interpreted as tuple constructor. zip function expects a list as its first argument but we are passing it a tuple.
So I'm trying to triplize an element, i.e. making 2 other copies of the element.
So I've written this:
triplize :: [a] -> [a]
triplize [x] = concatMap (replicate 3) [x]
But I've been getting this error:
Non-exhaustive patterns in function triplize
I'm new to Haskell, so any pointers are appreciated!
When you write
triplize [x]
You are saying that the argument must match the pattern [x]. This pattern represents a list with a single value, which will be assigned to the name x. Note that the list will not be assigned to the name x, only the single value in that list. If you tried calling your function with the list [] or [1, 2], it would cause an error because you haven't told your function what to do with those inputs.
What you probably want is
triplize x = concatMap (replicate 3) x
Here your pattern is just x, which matches any list, from the empty list to an infinite list. Notice that the patterns in your function definition match the way you make the values themselves. In Haskell you can pattern match on constructors, and lists can be constructed with square brackets and commas, or they can be constructed using the : operator, so [1, 2, 3] == (1:2:3:[]). In fact, the : operator is how Haskell represents lists internally.
An example that uses more pattern matches:
sumSuccessive :: [Int] -> [Int]
sumSuccessive [] = [] -- Empty list
sumSuccessive [x] = [x] -- Singleton list (only one value)
sumSuccessive (x:y:rest) = x + y : sumSuccessive rest
-- Match a list with at least two elements `x` and `y`,
-- with the rest of the list assigned to the name `rest`
This example function would take the list [1, 2, 3, 4] and return the list [3, 7] ([1 + 2, 3 + 4]).
You can define triplize as:
triplize :: [a] -> [a]
triplize x = concatMap (replicate 3) x
But there's even no need to write x:
triplize :: [a] -> [a]
triplize = concatMap (replicate 3)
The original code will work only on lists with one element:
> triplize [1]
[1, 1, 1]
> triplize []
*** Exception: Non-exhaustive patterns in function triplize
> triplize [0, 1]
*** Exception: Non-exhaustive patterns in function triplize
[x] matches a list of exactly one element. If you want to match any list, just remove [ and ]:
triplize x = concatMap (replicate 3) x
This would turn ["a", "b", "c"] into ["a", "a", "a", "b", "b", "b", "c", "c", "c"].
On the other hand, if you want to take one element and return a list (containing 3 of that element), then your code should be
triplize :: a -> [a]
triplize x = replicate 3 x
I have a given list, e.g. [2, 3, 5, 587] and I want to have a complete list of the combination. So want something like [2, 2*3,2*5, 2*587, 3, 3*5, 3*587, 5, 5*587, 587]. Since I am on beginner level with Haskell I am curious how a list manipulation would look like.
Additionally I am curious if the computation of the base list might be expensive how would this influence the costs of the function? (If I would assume the list has limit values, i.e < 20)
Rem.: The order of the list could be done afterwards, but I have really no clue if this is cheaper within the function or afterwards.
The others have explained how to make pairs, so I concern myself here with getting the combinations.
If you want the combinations of all lengths, that's just the power set of your list, and can be computed the following way:
powerset :: [a] -> [[a]]
powerset (x:xs) = let xs' = powerset xs in xs' ++ map (x:) xs'
powerset [] = [[]]
-- powerset [1, 2] === [[],[2],[1],[1,2]]
-- you can take the products:
-- map product $ powerset [1, 2] == [1, 2, 1, 2]
There's an alternative powerset implementation in Haskell that's considered sort of a classic:
import Control.Monad
powerset = filterM (const [True, False])
You could look at the source of filterM to see how it works essentially the same way as the other powerset above.
On the other hand, if you'd like to have all the combinations of a certain size, you could do the following:
combsOf :: Int -> [a] -> [[a]]
combsOf n _ | n < 1 = [[]]
combsOf n (x:xs) = combsOf n xs ++ map (x:) (combsOf (n - 1) xs)
combsOf _ _ = []
-- combsOf 2 [1, 2, 3] === [[2,3],[1,3],[1,2]]
So it seems what you want is all pairs of products from the list:
ghci> :m +Data.List
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- bs ]
[6,10,1174,15,1761,2935]
But you also want the inital numbers:
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- 1:bs ]
[2,6,10,1174,3,15,1761,5,2935,587]
This uses a list comprehension, but this could also be done with regular list operations:
ghci> concatMap (\a:bs -> a : map (a*) bs) . init $ tails [2, 3, 5, 587]
[2,6,10,1174,3,15,1761,5,2935,587]
The latter is a little easier to explain:
Data.List.tails produces all the suffixes of a list:
ghci> tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587],[]]
Prelude.init drops the last element from a list. Here I use it to drop the empty suffix, since processing that causes an error in the next step.
ghci> init [[2,3,5,587],[3,5,587],[5,587],[587],[]]
[[2,3,5,587],[3,5,587],[5,587],[587]]
ghci> init $ tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587]]
Prelude.concatMap runs a function over each element of a list, and combines the results into a flattened list. So
ghci> concatMap (\a -> replicate a a) [1,2,3]
[1, 2, 2, 3, 3, 3]
\(a:bs) -> a : map (a*) bs does a couple things.
I pattern match on my argument, asserting that it matches an list with at least one element (which is why I dropped the empty list with init) and stuffs the initial element into a and the later elements into bs.
This produces a list that has the same first element as the argument a:, but
Multiplies each of the later elements by a (map (a*) bs).
You can get the suffixes of a list using Data.List.tails.
This gives you a list of lists, you can then do the inner multiplications you want on this list with a function like:
prodAll [] = []
prodAll (h:t) = h:(map (* h) $ t)
You can then map this function over each inner list and concatenate the results:
f :: Num a => [a] -> [a]
f = concat . map prodAll . tails
I've been trying to wrap my head around this for a while now, but it seems like my lack of Haskell experience just won't get me through it. I couldn't find a similar question here on Stackoverflow (most of them are related to merging all sublists, without any condition)
So here it goes. Let's say I have a list of lists like this:
[[1, 2, 3], [3, 5, 6], [20, 21, 22]]
Is there an efficient way to merge lists if some sort of condition is true? Let's say I need to merge lists that share at least one element. In case of example, result would be:
[[1, 2, 3, 3, 5, 6], [20, 21, 22]]
Another example (when all lists can be merged):
[[1, 2], [2, 3], [3, 4]]
And it's result:
[[1, 2, 2, 3, 3, 4]]
Thanks for your help!
I don't know what to say about efficiency, but we can break down what's going on and get several different functionalities at least. Particular functionalities might be optimizable, but it's important to clarify exactly what's needed.
Let me rephrase the question: For some set X, some binary relation R, and some binary operation +, produce a set Q = {x+y | x in X, y in X, xRy}. So for your example, we might have X being some set of lists, R being "xRy if and only if there's at least one element in both x and y", and + being ++.
A naive implementation might just copy the set-builder notation itself
shareElement :: Eq a => [a] -> [a] -> Bool
shareElement xs ys = or [x == y | x <- xs, y <- ys]
v1 :: (a -> a -> Bool) -> (a -> a -> b) -> [a] -> [b]
v1 (?) (<>) xs = [x <> y | x <- xs, y <- xs, x ? y]
then p = v1 shareElement (++) :: Eq a => [[a]] -> [[a]] might achieve what you want. Except it probably doesn't.
Prelude> p [[1], [1]]
[[1,1],[1,1],[1,1],[1,1]]
The most obvious problem is that we get four copies: two from merging the lists with themselves, two from merging the lists with each other "in both directions". The problem occurs because List isn't the same as Set so we can't kill uniques. Of course, that's an easy fix, we'll just use Set everywhere
import Data.Set as Set
v2 :: (a -> a -> Bool) -> (a -> a -> b) -> Set.Set a -> Set.Set b
v2 (?) (<>) = Set.fromList . v1 (?) (<>) . Set.toList
So we can try again, p = v2 (shareElementonSet.toList) Set.union with
Prelude Set> p $ Set.fromList $ map Set.fromList [[1,2], [2,1]]
fromList [fromList [1,2]]
which seems to work. Note that we have to "go through" List because Set can't be made an instance of Monad or Applicative due to its Ord constraint.
I'd also note that there's a lot of lost behavior in Set. For instance, we fight either throwing away order information in the list or having to handle both x <> y and y <> x when our relation is symmetric.
Some more convenient versions can be written like
v3 :: Monoid a => (a -> a -> Bool) -> [a] -> [a]
v3 r = v2 r mappend
and more efficient ones can be built if we assume that the relationship is, say, an equality relation since then instead of having an O(n^2) operation we can do it in O(nd) where d is the number of partitions (cosets) of the relation.
Generally, it's a really interesting problem.
I just happened to write something similar here: Finding blocks in arrays
You can just modify it so (although I'm not too sure about the efficiency):
import Data.List (delete, intersect)
example1 = [[1, 2, 3], [3, 5, 6], [20, 21, 22]]
example2 = [[1, 2], [2, 3], [3, 4]]
objects zs = map concat . solve zs $ [] where
areConnected x y = not . null . intersect x $ y
solve [] result = result
solve (x:xs) result =
let result' = solve' xs [x]
in solve (foldr delete xs result') (result':result) where
solve' xs result =
let ys = filter (\y -> any (areConnected y) result) xs
in if null ys
then result
else solve' (foldr delete xs ys) (ys ++ result)
OUTPUT:
*Main> objects example1
[[20,21,22],[3,5,6,1,2,3]]
*Main> objects example2
[[3,4,2,3,1,2]]
I am new to both Haskell and programming. My question about binding in pattern-matched, recursive functions. For instance, suppose I have a function which checks whether a given list (x:xs) is a sublist of another list, (y:ys). My initial thought, following the examples in my textbook, was:
sublist [] ys = True
sublist xs [] = False
sublist (x:xs) (y:ys)
| x == y = sublist xs ys
| x /= y = sublist (x:xs) ys
This works on test data, e.g.,
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
where I expected it to fail. I expect it to fail, since
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
= sublist [2, 3] [2, 4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
at which point, I thought, [3] = 3:[] will be matched with (x:xs) in sublist, and [4, 1, 2, 3] will be matched with (y:ys) in sublist. How, then, is sublist working?
Edit: Thanks to everyone here, I think I've solved my problem. As noted, I was ("subconsciously") wanting sublist to backtrack for me. Using the last answer (BMeph) posted as a guide, I decided to approach the problem differently, in order to solve the "binding problem," i.e., the "backtracking" problem.
subseq :: (Eq a) => [a] -> [a] -> Bool
subseq [] _ = True
subseq _ [] = False
subseq (x:xs) (y:ys) =
-- subseq' decides whether the list bound to (x:xs) = M is a prefix of the list
-- bound to L = (y:ys); it recurses through L and returns a Bool value. subseq
-- recurses through M and L, returning a disjunction of Bool
-- values. Each recursive call to subseq passes M and ys to subseq', which
-- decides whether M is a prefix of the **current list bound to ys**.
let subseq' :: (Eq a) => [a] -> [a] -> Bool
subseq' [] _ = True
subseq' _ [] = False
subseq' (x:xs) (y:ys) = (x == y) && subseq' xs ys
in subseq' (x:xs) (y:ys) || subseq (x:xs) ys
It is working because:
[3] is matched as x:xs as 3:[],
[4, 1, 2, 3] is matched as y:ys as 4:[1,2,3]
3/=4 so sublist (x:xs) ys is evaluated, which eventually is True
trace:
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
= sublist [2, 3] [2, 4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
= sublist [3] [1, 2, 3]
= sublist [3] [2, 3]
= sublist [3] [3]
= sublist [] [] = True
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
= sublist [2, 3] [2, 4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
= sublist (3:[]) (4:[1,2,3]) -- Since 3 /= 4, we take sublist (x:xs) ys
= sublist (3:[]) [1,2,3]
= sublist (3:[]) (1:[2,3])
= sublist (3:[]) [2,3]
= sublist (3:[]) (2:[3])
= sublist (3:[]) [3]
= sublist [] []
= True
sublist checks if heads of lists are equal. If yes, then it removes them and proceeds (sublist xs ys). If no, it removes head from the second list (sublist (x:xs) ys). This way it "finds" the following association:
1 2 3
| | |
| | \-----\
| | |
1 2 4 1 2 3
In other words, to check sublist [1,2,3] ys for some list ys it pops elements from ys as long as they are not 1. Then it pops elements as long as they are not 2. Then it pops elements as long as they are not 3. If [1,2,3] is exhausted, then it reports True; if ys is exhausted, it reports False.
Debug.Trace is your friend. With sublist instrumented as
sublist [] ys = trace ("A: [] " ++ show ys) True
sublist xs [] = trace ("B: " ++ (show xs) ++ " []") False
sublist (x:xs) (y:ys)
| x == y = trace (info "C" "==")
sublist xs ys
| x /= y = trace (info "D" "/=")
sublist (x:xs) ys
where info tag op =
tag ++ ": " ++ (show x) ++ " " ++ op ++ " " ++ (show y) ++
"; xs=" ++ (show xs) ++ ", ys=" ++ show ys
you see what's happening, namely that it's repeatedly throwing away the head of the second list until it finds a match:
*Main> sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
C: 1 == 1; xs=[2,3], ys=[2,4,1,2,3]
C: 2 == 2; xs=[3], ys=[4,1,2,3]
D: 3 /= 4; xs=[], ys=[1,2,3]
D: 3 /= 1; xs=[], ys=[2,3]
D: 3 /= 2; xs=[], ys=[3]
C: 3 == 3; xs=[], ys=[]
A: [] []
True
Another tool that will help you implement sublist correctly is Test.QuickCheck, a library that automatically creates test data for use in verifying properties that you specify.
For example, say you want sublist to treat xs and ys as sets and determine whether the former is a subset of the latter. We can use Data.Set to specify this property:
prop_subsetOf xs ys =
sublist xs ys == fromList xs `isSubsetOf` fromList ys
where types = (xs :: [Int], ys :: [Int])
This says sublist should be equivalent to the definition on the right. The prop_ prefix is a popular convention for naming test properties to be used with QuickCheck.
Running it also identifies a failure case:
*Main> quickCheck prop_subsetOf
*** Failed! Falsifiable (after 6 tests):
[0,0]
[0]
I think where you may be misunderstanding, is that (when you first wrote the function) you assumed that in your check x /= y = sublist (x:xs) ys you (sub-consciously?) assumed that the function would backtrack and re-do your function with the tail of the original second list, not the tail of whichever piece of the list you're using when it doesn't match.
One nice (and unsettling) thing about Haskell is just how ridiculously powerful it is.
For an example, here's how what you wanted should have looked:
sublist [] ys = True
sublist xs [] = False
sublist (x:xs) (y:ys) | x /= y = False
| otherwise = sublist xs ys || sublist (x:xs) ys
which will check for all of the pieces of the first list. The "official" definition for the function (look up "isInfixOf" in your documentation) has a few extra functions that basically means the same thing.
Here's another way write it, that looks more "explanatory" to my eyes:
sublist [] ys = True
sublist xs [] = False
sublist xs ys = (xs == take (length xs) ys) || sublist xs (tail ys)
YuppieNetworking and sdcwc have already explained how the matching works. So your sublist searches for a sublist in the same sense as subsequence (not necessarily the same items in a row, there can be anything in between).
I want to note that you can often avoid explicit recursion to remove unnecessary items from the front of the list with dropWhile. Also, I wanted to give an example how to check if two lists have the same prefixes (you need this to check if the second list contains items of the first one in a row).
The first example is similar to your function, it allows for items in between, but it uses dropWhile to remove items in front of ys:
-- Test:
-- map ("foo" `subListOf`) ["kungfoo", "f-o-o!", "bar"] == [True,True,False]
[] `subListOf` _ = True
(x:xs) `subListOf` ys =
let ys' = dropWhile (/= x) ys -- find the first x in ys
in case ys' of
(_:rest) -> xs `subListOf` rest
[] -> False
The second example looks for a "dense" sublist:
-- Test:
-- map ("foo" `denseSubListOf`) ["kungfoo!", "-f-o-o-"] == [True,False]
[] `denseSubListOf` _ = True
_ `denseSubListOf` [] = False
xs `denseSubListOf` ys =
let ps = zip xs ys in
(length ps == length xs && all (uncurry (==)) ps) -- same prefix of xs and ys
|| xs `denseSubListOf` (tail ys) -- or search further
Please note that to check that the second list contains all the first one in the beginning I compare elements pair by pair (I zip them together to do it).
It is easier to explain by example:
zip [1,2,3] [1,2,3,4,5] -- gives [(1,1), (2,2), (3,3)], 4 and 5 are truncated
uncurry (==) -- an equivalent of (\(a,b) -> a == b)
all -- gives True iff (uncurry (==)) is True for all pairs
length ps == length xs -- this is to ensue that the right list is long enough