The program return all possible combinations of '0' and '1' length N.
addToElement :: String -> String -> String
addToElement element symbol = element ++ symbol
addOneToElement :: String -> String
addOneToElement element = addToElement element "1"
addZeroToElement :: String -> String
addZeroToElement element = addToElement element "0"
processListOnce :: [String] -> [String]
processListOnce lst = do
let s1 = map addOneToElement lst
let s2 = map addZeroToElement lst
s1 ++ s2
processList :: [String] -> Integer -> [String]
processList lst 1 = processListOnce lst
processList lst n = do
let tmp = processListOnce(lst)
processList tmp (n - 1)
{-
processList2 :: [String] -> Integer -> [String]
processList2 lst n = iterate (map processListOnce) lst !! n
-}
main = do
let s = processList ["0", "1"] 2
let ss = show s
putStrLn ss
It is my first Haskell program so I will be thankful if you help me:
First of all pls refactore my code Haskell-way. I already know one magic refactring:
Control.Monad.replicateM n [0,1]
but this solution is not good for studying purposes :)
Why I can not use ProcessList2 instead ProcessList and get error:
all_possible_combinations.hs:44:51:
Couldn't match expected type `[Char]' against inferred type `Char'
Expected type: [String]]
Inferred type: [String]
In the second argument of `iterate', namely `lst'
In the first argument of `(!!)', namely
`iterate (map processListOnce) lst'
Is there any way to skip (not use) the 'tmp' variable in the processList? I have tried, but got the error:
processList :: [String] -> Integer -> [String]
processList lst 1 = processListOnce lst
processList lst n = processList processListOnce(lst) (n - 1)
all_possible_combinations.hs:39:32:
Couldn't match expected type `[String]'
against inferred type `[String] -> [String]'
In the first argument of `processList', namely `processListOnce'
In the expression: processList processListOnce (lst) (n — 1)
In the definition of `processList':
processList lst n = processList processListOnce (lst) (n — 1)
Thanks in advance.
First of all pls refactore my code Haskell-way. I already know one magic refactring:
Control.Monad.replicateM n [0,1]
but this solution is not good for studying purposes :)
Actually, while I certainly wouldn't expect someone new to Haskell to come up with such a solution, I think that understanding this version would be very good for studying purposes.
The regular replicate function is pretty simple: It creates a list of the same element repeated some number of times. This is also the first step of what replicateM does:
> replicate 2 ["0", "1"]
[["0", "1"], ["0", "1"]]
The second step of what replicateM does is "sequence" the list according to the Monad of the elements, turning something a list of monadic values [m a] into a monadic list of values m [a]. What this does is "combine" the structure of each monadic value in some sense, where the specific meaning of "combine" depends on the specific monad.
As a Monad, lists represent something like trying multiple possibilities. So when we "sequence" the values, that means that at each step, every possibility is tried separately, and all possible results are collected.
So, ["0", "1"] is a monadic value representing trying two different possibilities. [["0", "1"], ["0", "1"]] is a list of that monadic value repeated twice. To sequence that list, we take each possibility from the first element of the list, use it as the head of the result list, then continue until reaching the end. Because each group of possibilities is the same, the final result is all the possible combinations of each possible item:
> replicateM 2 ["0", "1"]
[["0","0"],["0","1"],["1","0"],["1","1"]]
About making it Haskelly, here is a solution that is not pure magic (as the replicateM may be)
onesAndZeroes 0 = [[]]
onesAndZeroes n = [x:xs | x <- [0,1], xs <- onesAndZeroes (n-1)]
Since you are new to haskell, if you don't understand it, it might help to read about list comprehensions.
Is there any way to skip (not use) the 'tmp' variable in the processList? I have tried, but got the error:
This definition has used the wrong precedence. You should write
processList lst n = processList (processListOnce lst) (n - 1)
-- # ^ ^
Why I can not use ProcessList2 instead ProcessList and get error:
processListOnce is already a [String] -> [String] function. If you use map processListOnce it will become a [[String]] -> [[String]] function. Thus, remove the map.
processList2 lst n = iterate processListOnce lst !! n
Another solution:
onesAndZeroes n = combo n ["0", "1"]
where combo 1 cs = cs
combo n cs = combo (n-1) (f cs)
f = concatMap (\x -> ['0':x, '1':x])
Like others I think replicateM would be my first choice, but if I was to avoid that this would be my solution. Perhaps less clear/concise than the list comprehension solution, but I find tail call recursion quite elegant.
Related
I'm making some exercise to practice my Haskell skills. My task is to implement the Haskell function find by myself with the filter function.
I already implemented the find function without the filter function (see codeblock below) but now my problem is to implement it with filter function.
-- This is the `find` function without `filter` and it's working for me.
find1 e (x:xs)= if e x then x
else find1 e xs
-- This is the find function with the filter function
find2 e xs = filter e xs
The result of find1 is right
*Main> find1(>4)[1..10]
Output : [5].
But my actual task to write the function with filter gives me the
*Main> find2(>4)[1..10]
Output : [5,6,7,8,9,10].
My wanted result for find2 is the result of find1.
To "cut a list" to only have one, head element in it, use take 1:
> take 1 [1..]
[1]
> take 1 []
[]
> take 1 $ find2 (> 4) [1..10]
[5]
> take 1 $ find2 (> 14) [1..10]
[]
If you need to implement your own take 1 function, just write down its equations according to every possible input case:
take1 [] = []
take1 (x:xs) = [x]
Or with filter,
findWithFilter p xs = take1 $ filter p xs
Your find1 definition doesn't correspond to the output you show. Rather, the following definition would:
find1 e (x:xs) = if e x then [x] -- you had `x`
else find1 e xs
find1 _ [] = [] -- the missing clause
It is customary to call your predicate p, not e, as a mnemonic device. It is highly advisable to add type signatures to all your top-level definitions.
If you have difficulty in writing it yourself you can start without the signature, then ask GHCi which type did it infer, than use that signature if it indeed expresses your intent -- otherwise it means you've coded something different:
> :t find1
find1 :: (t -> Bool) -> [t] -> [t]
This seems alright as a first attempt.
Except, you actually intended that there would never be more than 1 element in the output list: it's either [] or [x] for some x, never more than one.
The list [] type is too permissive here, so it is not a perfect fit.
Such a type does exist though. It is called Maybe: values of type Maybe t can be either Nothing or Just x for some x :: t (read: x has type t):
import Data.Maybe (listToMaybe)
find22 p xs = listToMaybe $ filter p xs
We didn't even have to take 1 here: the function listToMaybe :: [a] -> Maybe a (read: has a type of function with input in [a] and output in Maybe a) already takes at most one element from its input list, as the result type doesn't allow for more than one element -- it simply has no more room in it. Thus it expresses our intent correctly: at most one element is produced, if any:
> find22 (> 4) [1..10]
Just 5
> find22 (> 14) [1..10]
Nothing
Do add full signature above its definition, when you're sure it is what you need:
find22 :: (a -> Bool) -> [a] -> Maybe a
Next, implement listToMaybe yourself. To do this, just follow the types, and write equations enumerating the cases of possible input, producing an appropriate value of the output type in each case, just as we did with take1 above.
You have a list with N elements
You only want to print elements that are not circular permuations of other elements of the same list
To check if two strings are the circular permutations of each other I do this, which works fine :
string1 = "abc"
string2 = "cab"
stringconc = string1 ++ string1
if string2 `isInfixOf` stringconc
then -- it's a circular permuation
else -- it's not
Edit : As one comment pointed that out, this test only work for strings of the same size
Back to the real use case :
checkClean :: [String] -> [String] -> IO String
checkClean [] list = return ""
checkClean (x:xs) list = do
let sequence = cleanInfix x list
if sequence /= "abortmath"
then putStr sequence
else return ()
checkClean xs list
cleanInfix :
cleanInfix :: String -> [String] -> String
cleanInfix seq [] = seq
cleanInfix seq (x:xs) = do
let seqconc = x ++ x
if seq `isInfixOf` seqconc && seq /= x
then "abortmath"
else cleanInfix seq xs
However this just outputs... nothing
With some research I found out that sequence in checkClean is always "abortmath"
Also I'm not quite comfortable with this "flag" abortmath, because if by any chance one element of the list is "abortmath", well..
For example :
if I have a list composed of :
NUUNNFFUF
FFUFNUUNN
I should write
NUUNNFFUF
I guess you call your initial code (question) with something like that:
result = ["NUUNNFFUF", "FFUFNUUNN"]
main = do
checkClean result result
It won't print anything because:
the first call of cleanInfix has the arguments following arguments: "NUUNNFFUF" and ["NUUNNFFUF", "FFUFNUUNN"]
in cleanInfix, since seq == x you have a recursive call with the following arguments: "NUUNNFFUF" and ["FFUFNUUNN"]
now, "NUUNNFFUF" is a real permutation of "FFUFNUUNN": cleanInfix returns "abortmath", and checkClean returns ()
then you have a recursive call of checkClean with following arguments: "FFUFNUUNN" and ["NUUNNFFUF", "FFUFNUUNN"]
again, "FFUFNUUNN" is a real permutation of "NUUNNFFUF": cleanInfix returns "abortmath", and checkClean returns ()
this is the end.
Basically, x is a permutation of y and y is a permutation of x, thus x and y are discarded.
Your answer works, but it is horribly complicated.
I won't try to improve either of your codes, but I will make a general comment: you should (you really should) avoid returning a monad when you don't need to: in the question, checkClean just needs to remove duplicates (or "circular duplicates") from a list. That's totally functional: you have all the information you need. Thus, remove those dos, lets and returns!
Now, let's try to focus on this:
You have a list with N elements You only want to print elements that are not circular permuations of other elements of the same list
Why don't you use your initial knowledge on circular permutations?
isCircPermOf x y = x `isInfixOf` (y ++ y)
Now, you need a function that takes a sequence and a list of sequences, and return only the elements of the second that are not circular permutations of the first :
filterCircDuplicates :: String -> [String] -> [String]
filterCircDuplicates seq [] = []
filterCircDuplicates seq (x:xs) =
if seq `isCircPermOf` x
then removeCircDuplicates seq xs
else x:removeCircDuplicates seq xs
This pattern is well know, and you can use filter to simplify it:
filterCircDuplicates seq l = filter (\x -> !seq `isCircPermOf` x) l
Or better:
filterCircDuplicates seq = filter (not.isCircPermOf seq)
Note the signature: not.isCircPermOf seq :: String -> Boolean. It returns true if the current element is not a circular permutation of seq. (You don't have to add the list argument.)
Final step: you need a function that takes a list and return this list without (circular) duplicates.
removeCircDuplicates :: [String] -> [String]
removeCircDuplicates [] = []
removeCircDuplicates (x:xs) = x:filterCircDuplicates x (removeCircDuplicates xs)
When your list has a head and a tail, you clean the tail, then remove the duplicates of the first element of the tail, and keep this first element.
Again, you have a well known pattern, a fold:
removeCircDuplicates = foldr (\x acc -> x:filterCircDuplicates x acc) []
It removes the duplicates from right to left.
And if you want a one-liner:
Prelude Data.List> foldr (\x -> ((:) x).filter(not.(flip isInfixOf (x++x)))) [] ["abcd", "acbd", "cdab", "abdc", "dcab"]
["abcd","acbd","abdc"]
The wonders you can make with a pen and some paper...
So if anyone is interested here is how I solved it, it's probably badly optimised but at least it works (I'm just trying to learn haskell, so it's good enough for now)
-- cleanInfix function
cleanInfix :: String -> [String] -> [String] -> [String]
cleanInfix sequence [] cleanlist = cleanlist
cleanInfix sequence (x:xs) cleanlist = do
-- this is where I check for the circular permuation
let sequenceconc = x ++ x
if sequence `isInfixOf` sequenceconc
then cleanInfix sequence xs (delete x cleanlist)
else cleanInfix sequence xs cleanlist
-- checkClean Function
checkClean :: [String] -> [String] -> [String] -> [String]
checkClean [] listesend cleanlist = cleanlist
checkClean (x:xs) listesend cleanlist = do
-- The first delete is to avoid checking if an element is the circular permuation of... itself, because it obviously is... in some way
let liste2 = cleanInfix x (delete x listesend) cleanlist
checkClean xs (delete x listesend) liste2
-- Clean function, first second and third are the command line argument don't worry about them
clean first second third = do
-- create of the result list by asking user for input
let printlist = checkClean result result result -- yes, it's the same list, three times
print printlist -- print the list
my function append takes a list of lists [[a], [b,c], [d,e]] and returns a single list [a,b,c,d,e].
I wrote this in a file so i didn't have to use "let" but i still get parse error on input '='. can anyone help?
thanks
append :: [[a]] -> [a]
append [[a]] = [ a | len = length a, n = 1, head a ++ (a !! n) , n < len]
You need let for len and n:
append [[a]] = [a | let len = length a, let n = 1, head a ++ (a !! n), n < len]
But this won't solve all of your problems, once the lets are added it doesn't typecheck, and [[a]] is probably not the pattern you want to use here. The pattern [[a]] will only match a list like [[1]], it won't match [], or [[1, 2]], or [[1], [2]].
You also have another problem that head a ++ (a !! n) should be an expression that returns a Bool, but in this case it's returning a list. Any "naked" expressions on the right side of the | in a list comprehension must evaluate to a Bool value.
If you're wanting to flatten a list of lists, I would suggest looking at the built-in concat function, which is actually defined using foldr. Folds can be tricky to learn, though, so I'll show an alternate definition using explicit recursion:
myconcat :: [[a]] -> [a]
myconcat [] = []
myconcat (x:xs) = x ++ myconcat xs
This is equivalent to the foldr definition, but hopefully it can be more instructive to how to solve this sort of problem.
You still need to use let to define local variables inside a list comprehension regardless of whether or not the code is in a file. The code being in a file only makes a difference for top-level definitions. Local definitions stay the same.
So the syntactically correct version of your code would be:
append :: [[a]] -> [a]
append [[a]] = [ a | let len = length a, let n = 1, head a ++ (a !! n) , n < len]
-- ^^^ ^^^
I know a bit of a Prolog and have just started some self-study in Haskell. I have been working through the 99 Problems for Haskell, learning much along the way and really enjoying Haskell. Sometimes I try to clarify my understanding of a problem space by coding something in Prolog and then thinking how that solution might relate to a functional approach in Haskell. Tonight, while working on the problems about logic (problems 47 and 48), I got distracted trying to accomplish the simple task of building up a list of the lists of all truth-value combinations with n values. I want a function tValues :: Int -> [[Bool]]. This problem can be solved in a very straightforward and declarative way in Prolog, e.g.:
combinations_of_n_truth_values(N, AllValues) :-
findall(Values, n_truth_values(N, Values), AllValues).
n_truth_values(N, TruthValues) :-
length(TruthValues, N),
maplist(truth_value, TruthValues).
truth_value(true).
truth_value(false).
When used, the variable AllValues will unify with the desired list of lists of truth-values. I would like to know how an experienced Haskell programmer would go about solving this same problem. I would expect there is an equally straightforward and declarative solution, but I can't seem to get my Haskell brain functioning in the right way.
I have fiddled with some semi-analogs using list comprehensions, such as the following:
tValues:: Int -> [[Bool]]
tValues 0 = []
tValues n = [v:vs | v <- tValue
, vs <- tValues (n-1) ]
tValue :: [Bool]
tValue = [True, False]
but tValues only returns []. I think I just need some human-to-human engagement to help shake my head clear and maybe grace me with a deeper insight.
Many thanks.
In pseudo-code, your list comprehension
[v:vs | v <- tValue
, vs <- tValues (n-1) ]
equals
for any combination of two elements in `tValue` and `tValues (n-1)`
cons the first onto the latter
However, tValues has no elements to begin with, it is an empty list. Lets simulate this for n = 1:
tValues 1 = [v:vs | v <- tValue
, vs <- tValues 0 ]
= [v:vs | v <- [True, False]
, vs <- [] ]
-- since there is no vs
= []
This propagates throughout the whole recursion. The solution is quite simple: change the base case to contain an empty combination:
tValues 0 = [[]] -- or: return []
Now the simulation yields:
tValues 1 = [v:vs | v <- tValue
, vs <- tValues 0 ]
= [v:vs | v <- [True, False]
, vs <- [[]]]
-- vs is []
= [True:[],False:[]]
= [[True],[False]]
Which is just what we wanted.
With the list monad,
g n = mapM (\_-> [True, False]) [1..n]
About your function's base case. As the function returns a list containing all truth-values lists of length n, it follows that for n=0 it should return a list containing all truth-values lists of length 0, i.e. a list containing one empty list.
truths :: [[Bool]]
truths = [True] : [False] : concatMap (\bs -> [True:bs, False:bs]) truths
truthValues :: Int -> [[Bool]]
truthValues n = dropWhile ((< n) . length) . takeWhile ((<= n) . length) $ truths
truths is an infinite list of all truth value combos, because the lengths increase monotonically we can just take the front part of the list while the lengths are less than or equal to the sets we're looking for, then drop the front of that whose lengths are less.
The reason you are only getting the empty list back is that eventually tValues (n-1) evaluates to tValues 0 which is of course the empty list. Trying to draw from the empty list in a list comprehension causes that iteration to fail. This propagates up the chain of comprehensions. Change the base case to tValues 1 = [[True], [False]] and it will work.
Not a complete answer per se, but if it interests you, with the list monad:
truthValues ∷ Int → [[Bool]]
truthValues 0 = return []
truthValues n = truthValues (n - 1) >>= (\l → [True:l, False:l])
or
truthValues n = foldM (\l _ -> [True:l, False:l]) [] [1..n]
or
truthValues = flip replicateM [True, False]
See also Will Ness' answer and the comments attached :)
I have to make a 2D list [[Int]]. out of a 1D list [Int] in Haskell.
The function should take to args "r" Int indicates the count of rows and a 1D list, which should be sliced into rows with the length of "r".
If length of the list is longer than r*r then the rest of the list should be dropped.
Howerver
If length of the list is shorter than r*r then the missing elements should be inserted in the list as 0.
Example 1:
Input:
r = 2
list = [1,2,3,4,5,6]
Output: [[1,2], [3,4]]
Example 2:
Input:
r = 3
list = [1,2,3,4,5,6]
Output: [[1,2,3], [4,5,6], [0,0,0]]
So my approach is over thre functions as follow:
zeroList :: Int -> [Int] -> [Int]
zeroList r myList = (take (r*r-(length myList)) (0 : zeroList r myList))
processList :: Int -> [Int] -> [[Int]]
processList r myList = (if (length myList < r*r)
then (myList:(zeroList r myList))
else if (length (myList > r*r))
then (reverse (drop r (reverse myList)))
else
myList)
make2DList :: Int -> [Int] -> [[Int]]
make2DList r myList = (if myList == []
then make2DList
else ( ( take r (processList r myList) ):( make2DList r ( drop r (processList r myList) ) )))
The zeroList function works properly but the other two functions don't work. I some compiling error messages:
D:\haskell\task1.hs:6:63:
Couldn't match expected type `[Int]' with actual type `Int'
Expected type: [[Int]]
Actual type: [Int]
In the return type of a call of `zeroList'
In the second argument of `(:)', namely `(zeroList r myList)'
D:\haskell\task1.hs:14:54:
Couldn't match expected type `[[Int]]'
with actual type `Int -> [Int] -> [[Int]]'
In the expression: make2DList
In the expression:
(if myList == [] then
make2DList
else
((take r myList) : (make2DList r (drop r myList))))
In an equation for `make2DList':
make2DList r myList
= (if myList == [] then
make2DList
else
((take r myList) : (make2DList r (drop r myList))))
Failed, modules loaded: none.
Prelude>
I can't comprehend, why it doesn't work although zeroList r myList. returns an ordinary list.
Could anyone help me please?
I have to admit that I don’t comprehend how you are trying to do it. All this if then else is quite unHaskellish. :-) Also, due to Haskell’s lazy evaluation and infinite lists, it is unnecessary to compute the exact number of needed zeroes etc. beforehand.
A rough draft how it could be done instead:
make2DList r l = take r . chunks r $ l ++ zeroes
where
zeroes = [0,0..]
chunks r xs = take r xs : chunks r (drop r xs)
Explanation:
Extend the list by an infinite number of zeroes so we don’t have to worry about padding anymore.
Make a chunks function that splits any list into chunks of the given length.
Apply chunks to the padded list.
Take as many rows as we need.
I can explain both of the compilation errors, and I have a question for you. I'll take the errors in reverse order.
Error at 14:54
First I'll explain how arguments are applied to functions in Haskell.
The function make2DList has type Int -> [Int] -> [[Int]], which is equivalent to Int -> ( [Int] -> [[Int]] ). This means that, if given one argument r (which must be of type Int) it returns a function of type [Int] -> [[Int]]. This returned function, if given an argument myList (which must be of type [Int]) returns a list of type [[Int]].
This means that the code make2DList r myList is equivalent to (make2DList r) myList. In any case, it must return a value of type [[Int]], that is, a list of lists of Ints.
But you have said that, in the event that myList is empty, it should return just make2DList. Unfortunately make2DList is a function of type Int -> [Int] -> [[Int]] and not a list of lists of type [[Int]], hence the compiler error message
Couldn't match expected type `[[Int]]'
with actual type `Int -> [Int] -> [[Int]]'
The fix is to supply some arguments to this call to make2DList. But do not supply an empty list as the second argument, or you will create an infinite loop. Probably what you actually want to do is to return an empty list of lists, written the same way as an empty list of anything: []
Edit: I should perhaps also explain how if ... then ... else works in Haskell. This is not at all like the if/then/else in imperative languages, and is actually just like the ternary operator. That is,
if a then b else c
in Haskell is, as far as I can tell, exactly the same as
a ? b : c
in another language.
Thus, in order for the whole expression (if a then b else c) to be of the right type, both b and c must be of the right type (and a must be boolean, of course). In your case, the whole if/then/else expression should be of type [[Int]] but your b is the expression make2DList (with no arguments), which is of course a function and not a list of lists as it should be.
Error at 6:63
The type of : is given by (:) :: a -> [a] -> [a]. This means that if whatever is on the left of the : has type a (for some a), then whatever is on the right should have type [a].
That is to say, whatever appears to the left of : will become the first element in the resulting list, and whatever is on the right of : will become the rest of the list, which means that the type of the rest of the list must be a list of the type of whatever the first element is.
Your first element is myList, which has type [Int], and what you're trying to use for the rest of the list is (zeroList r myList), which also has type [Int] and is thus only good as a single element.
Possible fixes (which would compile, but may or may not be correct) could include:
enclosing zeroList r myList in square brackets, thus:
myList:[zeroList r myList]
which would always create a list of two elements, each of which would be a list of Ints
concatenating the two lists, thus:
myList ++ (zeroList r myList)
but this would produce the wrong return type, so you'd have to put the result in another list. The following would compile, but is almost certainly not what you want:
[myList ++ (zeroList r myList)]
That r probably wants to be something like r - (length myList) or something too.
Question
I'm having trouble guessing how your functions are supposed to work. What are each of the two functions processList and make2DList supposed to do? I see that they both have the same type, so what is the difference?
import Data.List (replicate)
takeElse :: Int -> a -> [a] -> [a]
takeElse 0 _ _ = []
takeElse n alt [] = replicate n alt
takeElse n alt (x : xs) = x : takeElse (n - 1) alt xs
exotic :: Int -> a -> [a] -> [[a]]
exotic dum alt lst = exot dim lst
where
exot 0 _ = []
exot n xs = takeElse dim alt xs : exot (n - 1) (drop dim xs)
such that
exotic 3 0 [1,2,3,4] == [[1,2,3],[4,0,0],[0,0,0]]
exotic 1 ' ' "Hello" == ["H"]
exotic 4 ' ' "Hello" == ["Hell","o "," "," "]
takeElse 10 ' ' "Hello" == "Hello "