Reputation: 16027
I'm attempting problem 11 of "99 Haskell Problems." The problem description is pretty much:
Write a function
encodeModified
that groups consecutive equal elements, then counts each group, and separates singles from runs.For example:
Prelude> encodeModified "aaaabccaadeeee" [Multiple 4 'a',Single 'b',Multiple 2 'c', Multiple 2 'a',Single 'd',Multiple 4 'e']
Here's my working code:
module Batch2 where
import Data.List -- for `group`
data MultiElement a = Single a | Multiple Int a deriving (Show)
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map f . group
where f xs = case length xs of 1 -> Single (head xs)
_ -> Multiple (length xs) (head xs)
I'd like to take out that pesky repeated (head xs)
in the final two lines. I figured I could do so by treating the result of the case
clause as a partially applied data constructor, as follows, but no luck:
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map f . group
where f xs = case length xs of 1 -> Single
_ -> Multiple length xs
(head xs)
I also tried putting parenthese around the case
clause itself, but to no avail. In that case, the case
clause itself failed to compile (throwing an error upon hitting the _
symbol on the second line of the clause).
EDIT: this error was because I added a parenthesis but didn't add an extra space to the next line to make the indentation match. Thanks, raymonad.
I can also solve it like this, but it seems a little messy:
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map (\x -> f x (head x)) . group
where f xs = case length xs of 1 -> Single
_ -> Multiple (length xs)
How can I do this?
Upvotes: 0
Views: 97
Reputation: 16027
The function application operator $
can be used to make this work:
encodeModified = map f . group
where f xs = case length xs of 1 -> Single
_ -> Multiple (length xs)
$ head xs
Upvotes: 4
Reputation: 32455
You could match on xs
itself instead:
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map f . group
where f xs = case xs of (x:[]) -> Single x
(x:_) -> Multiple (length xs) x
or more tersely as
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map f . group
where f (x:[]) = Single x
f xs@(x:_) = Multiple (length xs) x
or even
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map f . group
where f as@(x:xs) = case xs of [] -> Single x
_ -> Multiple (length as) x
Admittedly most of these have some repetition, but not of function application.
You could also go with let
:
encodeModified :: (Eq a) => [a] -> [MultiElement a]
encodeModified = map f . group
where f xs = let x = head xs
len = length xs in
case len of 1 -> Single x
_ -> Multiple len x
Upvotes: 3