I need to define group function is Haskell, but i just can do it with takeWhile and dropWhile, but i cant do it with span.
And i need to do it with span!
Could you help me?
Here my code with tW and dW:
group' :: (Eq a) => [a] -> [[a]]
group' [] = []
group' (x:xs) = (x : takeWhile (== x) xs) : group' (dropWhile (== x) xs)
Try this.
group' (x:xs) = a:(group' b) where (a,b) = span (==x) (x:xs)
Span simply returns two lists, which are separated using the given function.
Looking at the definition of span in hackage, we find this useful hint:
span p xs is equivalent to (takeWhile p xs, dropWhile p xs)
So, as you defined your function as
group' [] = []
group' (x:xs) = (x : takeWhile (== x) xs) : group' (dropWhile (== x) xs)
You can easily see that your p in this case is (== x). So, replacing it in the span definition above
span p xs = (takeWhile p xs, dropWhile p xs)
span (== x) xs = (takeWhile (== x) xs, dropWhile (== x) xs)
span returns a pair of lists, so you can access them with fst and snd.
So we have that
takeWhile (== x) xs = fst (span (== x) xs)
and
dropWhile (== x) xs = snd (span (== x) xs)
Using this, we can then replace them in your original function like so:
group' [] = []
group' (x:xs) = (x : fst (span (== x) xs) ) : group' (snd (span (== x) xs) )
Of course it's not nice to call the same function with the same arguments twice (span (== x) xs), so let's call it just once with a let binding:
group' [] = []
group' (x:xs) = let s = span (== x) xs in (x : (fst s)) : group' (snd s)
I love how Haskell is just maths in the end, and you can replace some definition (like the one you used with takeWhile and dropWhile) with others (span) using just some algebraic equations!
Related
I'm trying to define the map function using foldr
I have found the two following solutions, however I'm not quite sure how they are working.
map' :: (a -> b) -> [a] -> [b]
map' f = foldr ((:) . f) []
map'' :: (a -> b) -> [a] -> [b]
map'' f = foldr (\x xs -> f x : xs) []
I'm quite new to Haskell and foldr, so I'm struggling to understand what ((:) . f) in the first solution and what (\x xs -> f x : xs) in the second solution do.
I also don't get how foldr is able handle the empty list case.
It would be much appreciated if I could get a simple step by step explanation of this, in layman's terms.
Both (\x xs -> f x : xs) and (:) . f mean the same thing. They're both functions that take two arguments, apply f to the first argument, and then cons that onto the second argument.
So what does foldr do when given an empty list? It simply returns the starting value, which in these examples is [].
Here is the implementation of foldr from Hackage:
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
I have written a program that takes a message as a string and returns an anagram by padding the message with X's as needed such that the string length has exactly 4 factors then essentially rearranges the message as if it had been organized in a grid and read down instead of across. For example, inputting, "Haskell" would return the string, "HealslkX". I have written a program that encodes this anagram, but am having trouble writing a program that can reverse the previous program and decode the anagram, particularly with the removeX function that should remove the X padding. Here is what I have:
encode:
import Data.List
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]
split :: Int -> [a] -> [[a]]
split _ [] = []
split n xs =
let (ys, zs) = splitAt n xs
in ys : split n zs
encode :: [Char] -> [Char]
encode (x:xs) = if (length (factors (length xs))) == 4 then concat
(transpose (split ((factors (length xs))!!2) xs))
else encode (xs ++ ['X'])
decode:
import Data.List
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]
split :: Int -> [a] -> [[a]]
split _ [] = []
split n xs =
let (ys, zs) = splitAt n xs
in ys : split n zs
removeX :: [a] -> [a]
removeX xs = if (last xs) == 'X' then ((init xs) && removeX xs)
else xs
decode :: [Char] -> [Char]
decode (x:xs) = removeX (concat (transpose (split ((factors (length xs))!!1) xs)))
Just use removeX (init xs) instead of init xs && removeX xs. Haskell is not procedural (you don't write down a sequence of changes to make) but functional (you write down functions that produce new results from old). Haven't read the rest of the code to see if there are other errors, though.
Also consider removeX = reverse . dropWhile ('X'==) . reverse for better efficiency. Lists are singly-linked, so accesses and modifications at the end are relatively expensive.
I'm learning Haskell. I defined the following function (I know I don't need addToList and I can also do Point-free notation I'm just in the process of playing with language concepts):
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = addToList (f x) map f xs
where
addToList :: a -> [a] -> [a]
addToList x [] = [x]
addToList x xs = x:xs
This produces a compile error:
with actual type `(a0 -> b0) -> [a0] -> [b0]'
Relevant bindings include
f :: a -> b (bound at PlayGround.hs:12:5)
map :: (a -> b) -> [a] -> [b] (bound at PlayGround.hs:11:1)
Probable cause: `map' is applied to too few arguments
In the second argument of `addToList', namely `map'
In the expression: addToList (f x) map f xs
If I put parantheses around map it works:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = addToList (f x) (map f xs)
where
addToList :: a -> [a] -> [a]
addToList x [] = [x]
addToList x xs = x:xs
I understand that function application binds more tightly than operators (as discussed in Haskell - too few arguments), however, I don't understand how the compiler would parse the above differently without the parantheses.
The simple way to see that something is wrong is to note that the expression:
addToList (f x) map f xs
is applying 4 arguments to addToList whereas:
addToList (f x) (map f xs)
is applying two arguments to addToList (which is what addToList "expects").
Update
Note that even though map takes two arguments, this expression:
addToList a map c d
is parsed as:
(((addToList a) map) c) d
So here's a possible explanation of what GHC is thinking...
addToList (f x) has type [a] -> [a] - i.e. it is a function which takes a list.
map has type (c -> d) -> [c] -> [d]. It is not a list, but with additional arguments it could produce a list.
So when GHC sees addTolist (f x) map and can't type check it, it sees that if map only had a few more arguments, like this:
addToList (f x) (map ...)
at least the second argument to addToList would be a list - so perhaps that's the problem.
Parsing is a distinct step that is completed before type checking occurs. The expression
addToList (f x) map f xs
has as much meaning to the parser as s1 (s2 s3) s4 s2 s5 has to you. It doesn't know anything about what the names mean. It takes the lexical structure of the string and turns it into a parse tree like
*5
/ \
/ xs
*4
/ \
/ f
*3
/ \
/ map
*2
/ \
addToList *1
/ \
f x
Once the parse tree is complete, then each node is tagged with its type, and type checking can occur. Since function application is denoted simply by juxtaposition, the type checker knows that the left child of a node is a function, the right child is the argument, and the root is the result.
The type checker can proceed roughly as follows, doing an pre-order traversal of the tree. (I'll alter the type signatures slightly to distinguish unrelated type variables until they are unified.)
addToList :: a -> [a] -> [a], so it takes an argument of type a and returns a function of type [a] -> [a]. The value of a is not yet known.
f :: b -> c, so it takes an argument of type b and returns a value of type c. The values of b and c are not yet known.
x has type d. The value of d is not yet known.
Letting b ~ d, f can be applied to x, so *1 :: c
Letting a ~ c, addToList is applied to *1, so *2 :: [a] -> [a]
Uh oh. *2 expects an argument of type [a], but it is being applied to map :: (e -> f) -> [e] -> [f]. The type checker does not know how to unify a list type and a function type, which produces the error you see.
I'm trying to write a function which adds parentheses like this: (parens '(a b c d e)) returns (a (b (c (d (e))))). I'm just not seeing the pattern very well. What I have so far just returns a list with parentheses around each element. I can't seem to figure out how to make it look like that.
(DEFUN PARENS (L)
(COND ((NULL L) NIL)
(T (CONS (LIST (CAR L)) (PARENS (CDR L))))))
There are no parenthesis in a list. You're starting with a list of five elements, (a b c d e), and getting back a list of two elements, (a (b (c (d (e))))). The first element is a, and the second is another list, (b (c (d (e)))).
It's very easy to get close to this using reduce:
CL-USER> (reduce 'list '(a b c d e) :from-end t)
(A (B (C (D E))))
You can think of reduce as "injecting" the function list into (a b c d e) to produce
(list a (list b (list c (list d e))))
It's almost what you want. You actually want:
(list a (list b (list c (list d (list e)))))
How would you produce that? You can recurse down the list, and for each sublist (x . ys) you want to return (list x (recurse ys)), with the exception being when ys is (). You don't want to recurse into (), because you don't want a list with two elements, you actually want nothing. So the trick is stop recursing earlier than you typically do with a list. Thus:
(defun parens (l)
(cond
((endp l) '())
((endp (rest l)) l)
((list (first l) (parens (rest l)))))) ; *
CL-USER> (parens '(a b c d e))
(A (B (C (D (E)))))
CL-USER> (parens '(a b))
(A (B))
CL-USER> (parens '(a))
(A)
CL-USER> (parens '())
NIL
*Omitting the t test in the last clause is intentional. If there are no body forms in a cond clause, then the value of the test is returned. Thus (list …) serves both as the test form and the value form.
We can actually clean that up a little bit. The case of ((endp l) '()) could be ((endp l) l) since l is the empty list. But that means that in both the first and second cases, we can return l. We can call (rest '()) in Common Lisp and get back (), so (rest l) will be () when l is something like (e) and when l is (). This means that we can use:
(defun parens (l)
(cond
((endp (rest l)) l)
((list (first l) (parens (rest l))))))
If we just have one test, though, we might as well just use if:
(defun parens (l)
(if (endp (rest l))
l
(list (first l) (parens (rest l)))))
You can actually do it with reduce and some special consideration for the end:
(defun unflatten (list)
(reduce #'list list
:from-end t
:end (1- (length list))
:initial-value (last list)))
Note that last returns a list of the last n (default 1) elements.
I'm trying to prove this lema
reverse-++ : ∀{ℓ}{A : Set ℓ}(l1 l2 : 𝕃 A) → reverse (l1 ++ l2) ≡ (reverse l2) ++ (reverse l1)
reverse-++ [] [] = refl
reverse-++ l1 [] rewrite ++[] l1 = refl
reverse-++ l1 (x :: xs) = {!!}
But another function, reverse-helper keeps coming up into my goal and I have no idea how I get rid of it. Any guidance or suggestions?
I'm assuming that in the implementation of reverse, you call reverse-helper. In that case, you probably want to prove a lemma about reverse-helper that you can call in the lemma about reverse. This is a general thing: If you are proving something about a function with a helper function, you usually need a proof with a helper proof, because the induction structure of the proof usually matches the recursion structure of the function.
I think you should start with the different argument.
Since ++ is probably defined with [] ++ a = a, and reverse (x :: xs) = (reverse xs) ++ (x :: nil) it will be better to prove reverse-++ (x :: xs) ys = cong (\xs -> xs ++ (x :: nil)) (reverse-++ xs ys)