Learning haskell: a recursive function for creating skip-bigrams - haskell

I'm working my way through the NLPWP Book, and I'm at the chapter that deals with recursive functions. A recursive function for computing bigrams looks like this:
bigram :: [a] -> [[a]]
bigram [] = []
bigram [_] = []
bigram xs = take 2 xs : bigram (tail xs)
And if I run it on the wordlist = ["colorless", "green", "ideas", "sleep", "furiously"] I get this:
bigram chomsky
[("colorless","green"),("green","ideas"),("ideas","sleep"),("sleep","furiously")]
The exercise says:
A skip-bigram is any pair of words in sentence order. Write a function skipBigrams that extracts skip-bigrams from a sentence as a list of binary tuples, using explicit recursion. Running your function on ["Colorless", "green", "ideas", "sleep", "furiously"] should give the following output:
Prelude> skipBigrams ["Colorless", "green", "ideas", "sleep", "furiously"]
[("Colorless","green"),("Colorless","ideas"),("Colorless","sleep"),("Colorless","furiously"),("green","ideas"),("green","sleep"),("green","furiously"),("ideas","sleep"),("ideas","furiously"),("sleep","furiously")]
Here is the definition I've tried:
skipBigram [] = []
skipBigram [_] = []
skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]
But I'm getting the following error:
Occurs check: cannot construct the infinite type: t ~ [(t, t)]
Relevant bindings include
xs :: [t] (bound at :3:15)
x :: t (bound at :3:13)
skipBigram :: [t] -> [(t, t)] (bound at :1:1)
In the expression: interactive:IHaskell384.skipBigram xs
In the expression: (x, interactive:IHaskell384.skipBigram xs)
Which, new to Haskell as I am, I don't understand in the slightest. What is an infinite type? A relevant binding?
How should I define skipBigram to resolve this compile-time error?

you get this because your result is a list-of-pairs, where the second-part of the first item in that list is some element and the second-part of the second item in your result list is, whatever you are trying to give back (you use recursion here so it will have the same type) - so you say:
my result is a list-of-tuples, but part of those tuples is the result-type itself
that is what the error tells you
here are some details:
look at your last line
skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]
you have a list of tuples on the right side so it's type will be like (based on the first element of the result list):
skipBigram :: [a] -> [(a,a)]
but in the second-item you have (x, skipBigram xs) meaning it will have the type (a, [(a,a)]) (remember the type of skipBigram xs is the above part).
and so - comparing the second parts of the tuples - you have a ~ [(a,a)] which produces your error because somehow the type a should be the same as [(a,a)] which you could expand in all eternity ;)
now to the algorithm itself:
It will not work like this - you somehow have to get all combinations and to do this you have to work with the items in the list.
Usually you either do this with list-comprehensions or with the do-notation of the list-monad.
To get going think about this:
f [] = [[]]
f (x:xs) =
let xss = f xs
in [ x:xs | xs <- xss ] ++ xss
test it and play with it in ghci - you will have to combine this with what you got somehow
(ok recursion.ninja ^^ spoiled your fun - I'll let this here anyway if you don't mind)

Try this definition:
skipBigram :: [a] -> [(a,a)]
skipBigram [] = [] -- nothing to do with an empty list
skipBigram (x:xs) = [(x,y) | y <- xs] ++ skipBigram xs
Your skipBigram function is generating all the "2-tuple left-to-right combinations" of words in the list. We can capture this concept with a simple list comprehension in the recursive definition. By recursively concatenating the simple list comprehensions, we gain the desired result list.

The infinite type error is complaining about your use of lists. Your function should have the type [a] -> [a] -> [(a, a)], but when GHC tries to infer your function's type, it gets that a = [a], an infinite type. Relevant bindings are just the types of other variables which may be causing the error.
However, even ignoring the type errors, your function will not do what you want at all. Firstly, your function will always return a list of length two, because you have explicitly constructed the list. Also, the result would include ("Colorless", "Colorless"), because (x, head xs) is the same here as (x, x).
Instead, try this solution
skipBigram :: [a] -> [(a, a)]
skipBigram [] = []
skipBigram (x:xs) = map (x,) xs ++ skipBigram xs
For this function to work, you will need to put the line
{-# LANGUAGE TupleSections #-}
at the beginning of your file.

Related

Symmetric Relation in Haskell

I'm working with relations and I want to find whether a relation is symmetric.
To find that a relation is symmetric, we need to find two tuples such that: [(a,b), (b,a)].
This is what I've got so far:
simmetry:: Eq a => [(a,a)] -> [a]
simmetry [] = []
simmetry (x:xs)
| (fst x `elem` map snd xs) && (snd x `elem` map fst xs) = fst x : (simmetry xs)
| otherwise = simmetry xs
What this function does is, it grabs a tuple x and checks that it finds its first element in another tuple as the second position, as well as checking that the second element is in another tuple as the first position.
However I'm missing out on the part where I have to check that the other tuple is the same one for both conditions. With my code, something like this: [(a,b),(b,c),(d,a)] would work.
P.D: simmetry returns [a] for testing purposes.
I'm out of ideas, any tips are highly appreciated!
What you want to check is: for every tuple (x,y) in the list, (y,x) should also be present. You can express that quite directly in Haskell:
isSymmetric :: Eq a => [(a,a)] -> Bool
isSymmetric l = all (\(x,y) -> (y,x)`elem`l) l
This is actually doing some redundant work because it always also goes over (x,y) itself, which your not really interested in, but it doesn't really matter. However it's a good exercise to design this in a way so it doesn't go over the element itself; for this it's helpful to use an auxiliary function
foci :: [a] -> [(a,[a])]
witht the behaviour
foci [p,q,r] ≡ [(p,[q,r]), (q,[p,r]), (r,[p,q])]
Then you left with an all over the foci of the input list, i.e.
isSymmetric = all _ . foci
With what #Rik Van Toor said:
simmetry:: Eq a => [(a,a)] -> [a]
simmetry [] = []
simmetry (x:xs)
| (snd x, fst x) `elem` xs = fst x : (simmetry xs)
| otherwise = simmetry xs

Duplicate elements of a list on even index

In Haskell, how do I implement a function dup that duplicates all elements that are on even positions (0,2,4...) in a list
dup :: [a] -> [a]
dup [] = []
dup (x:xs) = x : x : dup xs
//but only on even index ??
Example of call:
dup [1,5,2,8,4] = [1,1,5,2,2,8,4,4]
Well we can define two functions that perform mutual recursion: dupeven :: [a] -> [a] and dupodd :: [a] -> [a]. dupeven thus will duplicate the first element, and the pass recursively to dupodd. dupodd on the other hand only makes one copy of the head, and then perform recursion on dupeven. Like:
dupeven :: [a] -> [a]
dupeven [] = []
dupeven (x:xs) = x : x : dupodd xs
dupodd :: [a] -> [a]
dupodd [] = []
dupodd (x:xs) = x : dupeven xs
The nice thing is that we get two dupplicate variants. Furthermore both functions are rather simple: they only operate on two different patterns the empty list [] and the "cons" (:).
This thus works as expected, and furthermore we basically have an extra function at (rather) low implementation cost:
Prelude> dupeven [1,5,2,8,4]
[1,1,5,2,2,8,4,4]
Prelude> dupodd [1,5,2,8,4]
[1,5,5,2,8,8,4]
As other answers explain, you can write this function recursively from first principles, but I always think problems like these are interesting puzzles: how can you compose such a function from the existing base library?
First, whenever you want to index a list, you can zip it with a lazily evaluated infinite list:
Prelude> zip [0..] [1,5,2,8,4]
[(0,1),(1,5),(2,2),(3,8),(4,4)]
In this case, though, you don't really need to know the actual index values (0, 1, 2, 3, 4 and so on). Instead, you just need to know how many repetitions of each number you need. You can produce that knowledge by infinitely cycling through 2 and 1:
Prelude> take 10 $ cycle [2,1]
[2,1,2,1,2,1,2,1,2,1]
(The above example uses take 10 to stop evaluation of the list, which, otherwise, continues forever.)
You can zip (cycle [2,1]) with any input list to get a list of tuples:
Prelude> zip (cycle [2,1]) [1,5,2,8,4]
[(2,1),(1,5),(2,2),(1,8),(2,4)]
The first element of the tuple is how many times to repeat the second element.
You can use replicate to repeat any value a number of times, but you'll have to uncurry it to take a single tuple as input:
Prelude> uncurry replicate (2,1)
[1,1]
Prelude> uncurry replicate (1,5)
[5]
Notice that this function always returns a list, so if you do this over a list of tuples, you'll have a list of lists. To immediately flatten such a list, you can therefore use monadic bind to flatten the projection:
Prelude> zip (cycle [2,1]) [1,5,2,8,4] >>= uncurry replicate
[1,1,5,2,2,8,4,4]
You can, if you will, make a function out of it:
dup xs = zip (cycle [2,1]) xs >>= uncurry replicate
This function turns out to be parametrically polymorphic, so while you can use it with lists of integers, you can also use it with lists of characters:
Prelude> dup [1,5,2,8,4]
[1,1,5,2,2,8,4,4]
Prelude> dup "acen"
"aaceen"
You may want to make a mutually recursive set of functions
duplicate, duplicate' :: [a] -> [a]
duplicate [] = []
duplicate (x:xs) = x : x : duplicate' xs
duplicate' [] = []
duplicate' (x:xs) = x : duplicate xs
Or add a simple ADT to determine the next action
data N = O | T
duplicate = duplicate' T
duplicate' _ [] = []
duplicate' T (x:xs) = x : x : duplicate' O xs
duplicate' O (x:xs) = x : duplicate' T xs
But in all honesty, the best way of doing it is what #Simon_Shine suggested,
duplicate [] = []
duplicate (x:y:xs) = x : x : y : duplicate xs
duplicate (x:xs) = x : x : xs -- Here x is an even index and xs is an empty list

Haskell: Transposition on a list of strings

New to Haskell and the language has been fun so far. I am hoping for a good hint rather than an answer as I am enjoying the mind-altering that is Haskell.
Question: I have a list of strings and I would like to transpose them.
let x = ["hello", "world"]
would become
["hw", "eo", "lr", "ll", "od"]
What I have so far is this:
transposeString :: [a] -> [a]
transposeString ([]:_) = []
transposeString x = (map head x) : transposeString (map tail x)
I definitely know there is something wrong with the type signature. My rational is that
Let y = ["wow", "top"]
map head y
returns "wt" so recursing this on the rest of the list would work?
Thank you in advance for any hints.
Mind that you do not have to provide a type signature: the Haskell compiler can derive one. If you put your implementation in a file:
transposeString ([]:_) = []
transposeString x = (map head x) : transposeString (map tail x)
and query the type with :t in ghci, it returns:
*Main> :t transposeString
transposeString :: [[b]] -> [[b]]
This makes perfect sense:
you transpose a matrix, which is a list of lists. [[b]] is a list of lists of b elements; and
you can derive it from the implementation yourself: map head x means that elements of x must be a list ([b]) since we perform a mapping, we have to nest the list one additional level so [[b]]. The same for tail.
As far as I know, your implementation is correctly. You can specialize it by saying that [b] ~ String, thus adding a type signature for Strings:
transposeString :: [String] -> [String]
transposeString ([]:_) = []
transposeString x = (map head x) : transposeString (map tail x)
which again makes sense because String ~ [Char] thus b ~ Char. But there is not much point in specializing a functions type: you better always use the most generic type signature. In this case [[b]] -> [[b]].
One point of note. Your type signature for tranposeString allows to accept a flat list as an argument. Tranposing a [String] works because [String]s are really just [[Char]]s, but what happens when you try to call transposeString on an [Int]? After all, the type signature allows for it.
On a side note, I ask you, given your current function, what would happen if your called transposeString []?
Do remember String is [Char]
"abc" == 'a' : 'b' : 'c' : []
From here you can use traversable nature of lists:
transpose :: [[a]] -> [[a]]
transpose mat = getZipList $ sequenceA $ map ZipList mat
test' = transpose [[1,2,3],[4,5,6],[7,8,9]] -- == [[1,4,7],[2,5,8],[3,6,9]]
test'' = transpose ["abc", "deg", "klm"] -- == ["adk","bel","cgm"]
You can also check default implementation of transponse in haskell doc
https://hackage.haskell.org/package/base-4.12.0.0/docs/src/Data.OldList.html#transpose
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([] : xss) = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])

Haskell Split List Function Infinite Type Error

I am working on a function in Haskell that will take one list and divide it into two evenly sized lists. Here is what I have:
split (x:y:xs) = split2 ([((length(x:y:xs) `div` 2)-2) : x ++ y] : [xs])
split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])
split2 (0:xs:[y:ys]) = (xs:[y:ys])
The function takes the first two elements of a list, and puts them together into list #2 and appends the first list as a second element. It then gets the length of the list, and divides it by two to find out how many times to run taking into account the fact that it already removed two elements from the first list. It then takes those two pieces of information and puts it into split2, which takes another element from the first list and appends it to the second list in the first element, also it counts down 1 from the number of runs and then runs again.
Problem is, when I run it I get this:
Functions.hs:19:49:
Occurs check: cannot construct the infinite type: t0 = [t0]
In the first argument of `(:)', namely `(y)'
19 refers to line 2, the first split2 function. Not exactly sure how to go about fixing this error. Any ideas?
It's hard to know where to start...
Let's define functions from ever larger chunks of the expression in split2.
f1 (x:y:xs) = (length(x:y:xs) `div` 2)-2
f1 :: [a] -> Int
Ok, so the argument is a list of something, and it returns an Int
f2 (x:y:xs) = ((length(x:y:xs) `div` 2)-2) : x
f2 :: [[Int]] -> [Int]
Here, the length Int is being cons'd with x, so x must be [Int], so (x:y:xs) must be [[Int]]. We can also infer that y has the same type as x, and xs is a list of things of the same type; [[Int]]. So the x ++ y will also be [Int].
So, [xs] will have type [[[Int]]]. Now, we wrap the result in a list constructor, and cons it with [xs]:
f3 (x:y:xs) = [((length(x:y:xs) `div` 2)-2) : x ++ y] : [xs]
f3 :: [[Int]] -> [[[Int]]]
I'm guessing you didn't expect the argument to be a list of lists of lists of Ints.
Now, if we look at split2, the argument pattern (x:xs:[y:ys]) implies that it is of type:
split2 :: [[a]] -> b
x :: [a]
xs :: [a]
y :: a
ys :: [a]
The rhs of the first definition of split2 tries to construct a new list by concatenating (x-1) : [xs] and y : [ys]. However, if we substitute the types into the y : [ys], we find:
y : [ys] :: a : [[a]]
But since (:) :: a -> [a] -> [a], this means that [[a]] must be the same type as [a], or a must be a list of itself, which is not possible.
The (x-1) is also badly typed, because it attempts to subtract one from a list.
I can't tell if you want to split the lists into even and odd elements, or into first and second halves.
Here are two versions that split into the first and second halves, rounding down (RD) or up (RU) if the length is odd:
splitRD xs = splitAt (length xs `div` 2) xs
splitRU xs = splitAt ((length xs + 1) `div` 2) xs
Here's a version that splits the list into even and odd elements:
splitEO [] = ([], [])
splitEO [e] = ([e], [])
splitEO (e:o:xs) = (e:es, o:os) where (es, os) = splitEO xs
Few suggestions
Write types to all the functions. It makes the code more readable and also helps catching errors.
The type of ++ is [a] -> [a] -> [a] and you are adding length of a list along with elements. Since list has to be of uniform type and length returns Int type, so compiler infers type of split as
[[Int]] -> t (assuming split2 returns type t).
When you pass ([((length(x:y:xs)div2)-2) : x ++ y] : [xs]) to split2.
xs is of type [[Int]] which means
[xs] is of type [[[Int]]]
, so compiler infers type of split2 to [[[Int]]] -> t.
Now in the definition of split2
split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])
ys is of type [[Int]], so y is of type [Int]. xs is of type [[Int]], but you are doing [xs] ++ y, which means both [xs] and y should be of same type ( [a] for some a).
Since you have not provided any types compiler is totally confused how to infer such type.
If you simply want to split the list into two equal parts why not do something more simpler like
split3 :: [a] -> ([a], [a])
split3 [] = ([],[])
split3 [x] = ([x],[])
split3 (x:y:xs) = let (xs',ys') = split3 xs in (x:xs',y:ys')
You seem to be passing state around in a list instead of as values to a function, which creates problems when it seems to the compiler as though you're creating a list of heterogenous values, whereas lists in Haskell are supposed to be of homogenous type.
Instead of
split2 (0:xs:[y:ys])
you should pass the different arguments/values to the function separately like this
split2 n xs (y:ys)
The functionality you're looking for is also reproduced in standard library functions.
halveList xs = splitAt (length xs `div` 2) xs
In Haskell, the elements of a list need to be all of the same type. In your function the lists contain a mixture of Ints, elements of the original list, and sublists of the original list, all of which are probably different types.
You also have some confusion about how to append lists and elements. x ++ y can only be used when x and y are themselves lists, while x : y can only be used when y is a list and x is an element of a list; to make a new list containing x and y as elements instead use [x, y] (although x:[y] also works). Similarly [xs] ++ y needs to be xs ++ [y] instead.
Without changing your basic algorithm, the simplest solution is probably to let split2 take 3 separate arguments.
split (x:y:xs) = split2 ((length(x:y:xs) `div` 2)-2) [x,y] xs
split2 n xs (y:ys) = split2 (n-1) (xs++[y]) ys
split2 0 xs ys = [xs,ys]

Learning Haskell: confusion with reverse function and recursion

I've just started to learn Haskell and I am trying to write a simple function that takes a list of strings and reverses each string in the list:
revComp :: [String] -> [String]
revComp [] = []
revComp [x] = [] ++ [reverse x]
revComp (x:xs) = revComp [xs]
When I try to load my code in GHCI, I get an error:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: String
Actual type: [String]
Could anyone explain what and where my problem is? Thanks very much.
The first three lines are fine. Your type signature is correct, the second line is correct, and so is the third. (However, [] ++ [reverse x] is the same as [reverse x].)
The fourth line, however, is wrong. Not only do you not use x at all on the right-hand side, but you have a type error: revComp [xs] calls revComp with a single-element list that has xs as its only element. Here, x is the first element of the list, and xs is the rest of the list. So, since xs has the type [String], [xs] has the type [[String]], but revComp takes a [String]! You want to reverse x, and prepend that to the result of reversing the rest of the list.
You can use revComp xs to reverse each string in the rest of the list, and (:) to prepend a value to a list (with the same syntax seen in the x:xs pattern you used on the left-hand side). That should be enough information for you to fix the last line. This makes the third line redundant, by the way, since [x] is just x:[].
ehird's answer is really complete, but I wanted to point out -- as a reference -- the "good/shorter" way to implement that function in real code, since you're new.
It can be defined as the partial application of map to reverse:
Prelude> let revComp = map reverse
Prelude> revComp ["olleh", "dlrow"]
["hello","world"]
It results in a function revComp :: [[a]] -> [[a]] (and not [String] -> [String] since both map and reverse work on any type of lists) that maps reverse to every element of the input list, returning the list of results.
The third line might not be required even with your example. The edge case (terminating condition) can be only the empty list. You can skip the condition for the single element.
revComp :: [String] -> [String]
revComp [] = []
revComp (x:xs) = reverse x : revComp xs
Don't know if there is a CS term for this. Someone in the community can add that information.
A few more ways to do the same thing:
revstr [] = []
revstr (x:xs) = reverse x : revstr xs
revstr2 [] = []
revstr2 (x:xs) = [reverse x] ++ revstr2 xs
revstr3 xs = map reverse xs
revstr4 = map reverse -- map takes 2 arguments ;)
revstr5 xs = foldl step [] xs
where step acc x = acc ++ [reverse x]
revstr6 xs = foldr step [] xs
where step x acc = reverse x : acc

Resources