Convert Tuple into Foldable - haskell

Is there a way to derive Foldable from Tuple?
At least when the tuple is homogeneous?
For example let's say I have (1,2,3) and I want to reverse it or to transform it into [1,2,3] and similar things.
I've tried to do something like
over each (\x -> 4 -x) (1,2,3) -- lol
but I need a sort of equivalent of fold with lens...
and actually I see that I can do
foldr1Of each (\a x -> a+x) (1,2,3)
but I would need instead
foldr1Of each (\a x -> a:x) (1,2,3)
which doesn't compile

but I would need instead
foldr1Of each (\a x -> a:x) (1,2,3)
which doesn't compile
The reason why this does not compile is because (:) :: a -> [a] -> [a] expects a list as second argument, but with foldr1Of, you provide it the last element of your fold, which is here a number.
You can solve it by using foldrOf :: Getting (Endo r) s a -> (a -> r -> r) -> r -> s -> r instead:
Prelude Control.Lens> foldrOf each (:) [] (1,2,3)
[1,2,3]
Here we thus pass [] as the "initial accumulator".
We can thus convert several several "containers" to lists with:
toList :: Each s s a a => s -> [a]
toList = foldrOf each (:) []
For example:
Prelude Control.Lens> toList (1,2)
[1,2]
Prelude Control.Lens> toList (1,2,3)
[1,2,3]
Prelude Control.Lens> toList (1,2,3,4)
[1,2,3,4]
Prelude Control.Lens> toList [1,2,3]
[1,2,3]
Prelude Control.Lens> toList Nothing
[]
Prelude Control.Lens> toList (Just 2)
[2]

In addition to Willem's answer, it is worth noting that Control.Lens.Fold offers analogues for pretty much everything in Data.Foldable. That includes toList, which becomes toListOf:
GHCi> toListOf each (1,2,3)
[1,2,3]

Related

Given a list, how can I perform some transformation only on sub-lists whose each two elements satisfy a binary predicate?

(In my actual use case I have a list of type [SomeType], SomeType having a finite number of constructors, all nullary; in the following I'll use String instead of [SomeType] and use only 4 Chars, to simplify a bit.)
I have a list like this "aaassddddfaaaffddsssadddssdffsdf" where each element can be one of 'a', 's', 'd', 'f', and I want to do some further processing on each contiguous sequence of non-as, let's say turning them upper case and reversing the sequence, thus obtaining "aaaFDDDDSSaaaSSSDDFFaFDSFFDSSDDD". (I've added the reversing requirement to make it clear that the processing involves all the contiguous non 'a'-s at the same time.)
To turn each sub-String upper case, I can use this:
func :: String -> String
func = reverse . map Data.Char.toUpper
But how do I run that func only on the sub-Strings of non-'a's?
My first thought is that Data.List.groupBy can be useful, and the overall solution could be:
concat $ map (\x -> if head x == 'a' then x else func x)
$ Data.List.groupBy ((==) `on` (== 'a')) "aaassddddfaaaffddsssadddssdffsdf"
This solution, however, does not convince me, as I'm using == 'a' both when grouping (which to me seems good and unavoidable) and when deciding whether I should turn a group upper case.
I'm looking for advices on how I can accomplish this small task in the best way.
You could classify the list elements by the predicate before grouping. Note that I’ve reversed the sense of the predicate to indicate which elements are subject to the transformation, rather than which elements are preserved.
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Arrow ((&&&))
import Data.Function (on)
import Data.Monoid (First(..))
mapSegmentsWhere
:: forall a. (a -> Bool) -> ([a] -> [a]) -> [a] -> [a]
mapSegmentsWhere p f
= concatMap (applyMatching . sequenceA) -- [a]
. groupBy ((==) `on` fst) -- [[(First Bool, a)]]
. map (First . Just . p &&& id) -- [(First Bool, a)]
where
applyMatching :: (First Bool, [a]) -> [a]
applyMatching (First (Just matching), xs)
= applyIf matching f xs
applyIf :: forall a. Bool -> (a -> a) -> a -> a
applyIf condition f
| condition = f
| otherwise = id
Example use:
> mapSegmentsWhere (/= 'a') (reverse . map toUpper) "aaassddddfaaaffddsssadddssdffsdf"
"aaaFDDDDSSaaaSSSDDFFaFDSFFDSSDDD"
Here I use the First monoid with sequenceA to merge the lists of adjacent matching elements from [(Bool, a)] to (Bool, [a]), but you could just as well use something like map (fst . head &&& map snd). You can also skip the ScopedTypeVariables if you don’t want to write the type signatures; I just included them for clarity.
If we need to remember the difference between the 'a's and the rest, let's put them in different branches of an Either. In fact, let's define a newtype now that we are at it:
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE ViewPatterns #-}
import Data.Bifoldable
import Data.Char
import Data.List
newtype Bunched a b = Bunched [Either a b] deriving (Functor, Foldable)
instance Bifunctor Bunched where
bimap f g (Bunched b) = Bunched (fmap (bimap f g) b)
instance Bifoldable Bunched where
bifoldMap f g (Bunched b) = mconcat (fmap (bifoldMap f g) b)
fmap will let us work over the non-separators. fold will return the concatenation of the non-separators, bifold will return the concatenation of everything. Of course, we could have defined separate functions unrelated to Foldable and Bifoldable, but why avoid already existing abstractions?
To split the list, we can use an unfoldr that alternately searches for as and non-as with the span function:
splitty :: Char -> String -> Bunched String String
splitty c str = Bunched $ unfoldr step (True, str)
where
step (_, []) = Nothing
step (True, span (== c) -> (as, ys)) = Just (Left as, (False, ys))
step (False, span (/= c) -> (xs, ys)) = Just (Right xs, (True, ys))
Putting it to work:
ghci> bifold . fmap func . splitty 'a' $ "aaassddddfaaaffddsssadddssdffsdf"
"aaaFDDDDSSaaaSSSDDFFaFDSFFDSSDDD"
Note: Bunched is actually the same as Tannen [] Either from the bifunctors package, if you don't mind the extra dependency.
There are other answers here, but I think they get too excited about iteration abstractions. A manual recursion, alternately taking things that match the predicate and things that don't, makes this problem exquisitely simple:
onRuns :: Monoid m => (a -> Bool) -> ([a] -> m) -> ([a] -> m) -> [a] -> m
onRuns p = go p (not . p) where
go _ _ _ _ [] = mempty
go p p' f f' xs = case span p xs of
(ts, rest) -> f ts `mappend` go p' p f' f rest
Try it out in ghci:
Data.Char> onRuns ('a'==) id (reverse . map toUpper) "aaassddddfaaaffddsssadddssdffsdf"
"aaaFDDDDSSaaaSSSDDFFaFDSFFDSSDDD"
Here is a simple solution - function process below - that only requires that you define two functions isSpecial and func. Given a constructor from your type SomeType, isSpecial determines whether it is one of those constructors that form a special sublist or not. The function func is the one you included in your question; it defines what should happen with the special sublists.
The code below is for character lists. Just change isSpecial and func to make it work for your lists of constructors.
isSpecial c = c /= 'a'
func = reverse . map toUpper
turn = map (\x -> ([x], isSpecial x))
amalgamate [] = []
amalgamate [x] = [x]
amalgamate ((xs, xflag) : (ys, yflag) : rest)
| xflag /= yflag = (xs, xflag) : amalgamate ((ys, yflag) : rest)
| otherwise = amalgamate ((xs++ys, xflag) : rest)
work = map (\(xs, flag) -> if flag then func xs else xs)
process = concat . work . amalgamate . turn
Let's try it on your example:
*Main> process "aaassddddfaaaffddsssadddssdffsdf"
"aaaFDDDDSSaaaSSSDDFFaFDSFFDSSDDD"
*Main>
Applying one function at a time, shows the intermediate steps taken:
*Main> turn "aaassddddfaaaffddsssadddssdffsdf"
[("a",False),("a",False),("a",False),("s",True),("s",True),("d",True),
("d",True),("d",True),("d",True),("f",True),("a",False),("a",False),
("a",False),("f",True),("f",True),("d",True),("d",True),("s",True),
("s",True),("s",True),("a",False),("d",True),("d",True),("d",True),
("s",True),("s",True),("d",True),("f",True),("f",True),("s",True),
("d",True),("f",True)]
*Main> amalgamate it
[("aaa",False),("ssddddf",True),("aaa",False),("ffddsss",True),
("a",False),("dddssdffsdf",True)]
*Main> work it
["aaa","FDDDDSS","aaa","SSSDDFF","a","FDSFFDSSDDD"]
*Main> concat it
"aaaFDDDDSSaaaSSSDDFFaFDSFFDSSDDD"
*Main>
We can just do what you describe, step by step, getting a clear simple minimal code which we can easily read and understand later on:
foo :: (a -> Bool) -> ([a] -> [a]) -> [a] -> [a]
foo p f xs = [ a
| g <- groupBy ((==) `on` fst)
[(p x, x) | x <- xs] -- [ (True, 'a'), ... ]
, let (t:_, as) = unzip g -- ( [True, ...], "aaa" )
, a <- if t then as else (f as) ] -- final concat
-- unzip :: [(b, a)] -> ([b], [a])
We break the list into same-p spans and unpack each group with the help of unzip. Trying it out:
> foo (=='a') reverse "aaabcdeaa"
"aaaedcbaa"
So no, using == 'a' is avoidable and hence not especially good, introducing an unnecessary constraint on your data type when all we need is equality on Booleans.

Control.Applicative lifting on n-lists

I am quite new to Haskell and would like to know how to achieve the following output without using a fixed comprehension list (or indeed an applicative functor like liftA) i.e.
> [ [x+y+z] | x <- [1,11], y <- [1,11], z <- [1,11]]
> [[3],[13],[13],[23],[13],[23],[23],[33]]
The above code example only processes 3 lists e.g. xyz. How can I achieve the same thing using n lists e.g. e.g. [[1,11]] or [[1,11],[1,11],[1,11],[1,11],[1,11]] ?
PS - I looked at using a control Applicative functor liftA but its limited to liftA3 e.g.
λ> :m + Control.Applicative
λ> let combine = liftA2 (,)
λ> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]
Thanks.
If you are using n copies of the same list [1,11] you can use replicateM:
import Control.Monad
ghci> replicateM 3 [1,11]
[[1,1,1],[1,1,11],[1,11,1],[1,11,11],[11,1,1],[11,1,11],[11,11,1],[11,11,11]]
ghci> map sum (replicateM 3 [1,11])
[3,13,13,23,13,23,23,33]
In general, you can use sequence to perform a multi-list cartesian product:
ghci> sequence [ [1,11], [2,22], [3,33] ]
[[1,2,3],[1,2,33],[1,22,3],[1,22,33],[11,2,3],[11,2,33],[11,22,3],[11,22,33]]
More generally, what you want is the Cartesian product of all the lists in a given list. Once you have that, then you can combine them in any way you like.
cartesian :: [[a]] -> [[a]]
cartesian [] = [[]]
cartesian (xs:xss) = [x : ys | x <- xs, ys <- cartesian xss]
mkSums :: [[Int]] -> [[Int]]
mkSums = map ((\x -> [x]) . sum) . cartesian
If you want the flexibility of handling inputs that aren't just lists of [1,11]:
λ> import Control.Applicative (liftA2)
λ> let sumsOfCombinations xs = (:[]) . sum <$> foldr (liftA2 (:)) [[]] xs
You can pass it any list of list of numbers:
λ> sumsOfCombinations' [[0,100],[-1,0,1],[0,1000]]
[-1,999,0,1000,1,1001,99,1099,100,1100,101,1101]
Including, but not limited to, your example:
λ> sumsOfCombinations $ replicate 3 [1,11]
[[3],[13],[13],[23],[13],[23],[23],[33]]
λ> sumsOfCombinations $ replicate 4 [1,11]
[[4],[14],[14],[24],[14],[24],[24],[34],[14],[24],[24],[34],[24],[34],[34],[44]]
Here is its type:
λ> :t sumsOfCombinations
sumsOfCombinations :: (Num b, Foldable t) => t [b] -> [[b]]
As written, sumsOfCombinations gives you the exact output you are looking for. However, I don't think it is necessary to return a list of lists, so I would choose:
λ> let sumsOfCombinations' xs = sum <$> foldr (liftA2 (:)) [[]] xs
λ> :t sumsOfCombinations'
sumsOfCombinations' :: (Num b, Foldable t) => t [b] -> [b]
λ> sumsOfCombinations' $ replicate 3 [1,11]
[3,13,13,23,13,23,23,33]
Note that you can extract a helper from each of these to give you the combinations of elements from the lists:
λ> let combinations = foldr (liftA2 (:)) [[]]
λ> combinations [[1,2],[3,4],[5,6]]
[[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]
So then you have:
sumsOfCombinations xs = (:[]) . sum <$> combinations xs
or, if you don't need to return a list of lists:
sumsOfCombinations' xs = sum <$> combinations xs

Haskell Applicative [] why can I not replace pure[] with [] in function?

ghci> :t pure []
pure [] :: Applicative f => f [a]
ghci> pure []
[]
ghci> :t []
[] :: [a]
ghci> fmap ((:) 2) (pure [])
[2]
ghci> fmap ((:) 2) ([])
[]
I would have thought replacing pure[] with [] in fmap ((:) 2) (pure []) would result in the same outcome.. who can explain the difference to me?
The type of pure is Applicative f => a -> f a so pure []
has type Applicative f => f [a]. You can specify f explicitly for different applicative types e.g.
pure [] :: Maybe [String] //Just []
pure [] :: IO [String] //displays '[]' in ghci
pure [] :: [[String]] //[[]]
The type of fmap ((:) 2) (pure []) is (Applicative f, Num a) => f [a]. Since Ghci runs in the IO monad, which is an Applicative, it chooses f to be IO, and displays the resulting list [2] which is what you see.
You can specify the applicative type directly to see a different result e.g.
fmap ((:) 2) (pure []) :: (Maybe [Int])
which is Just [2]
In fmap ((:) 2) ([]), there are no elements in the input list so you get an empty list.
Why would it be the same? They're different expressions.
Perhaps it simplifies things if we just look at lists. So, there's the empty list []. Its type can be anything with brackets around it, in particular also a nested list:
Prelude> [] :: [[Int]]
[]
But there's also another "empty nested list":
Prelude> [[]] :: [[Int]]
[[]]
This one isn't really empty though, it merely contains only the empty list. ([[],[],[],...] would also be possible). In fact, that would be the result of what you've tried, if done in the list applicative:
Prelude Control.Applicative> pure [] :: [[Int]]
[[]]
It is certainly not the same as the empty list,
Prelude> [[]] == []
False
In particular,
Prelude> (length [], length [[]])
(0,1)
And fmappming over an empty list never does anything, while fmapping over an empty-containing list will call the function with []: an easy way to see this is
Prelude Control.Applicative> fmap undefined []
[]
Prelude Control.Applicative> fmap undefined [[]]
[* Exception: Prelude.undefined
The real confusing thing about your trials is that ghci silently uses the IO monad.
There's also a subclass of Applicative for actual emptiness:
Prelude Control.Applicative> :i Alternative
class Applicative f => Alternative f where
  empty :: f a
  (<‌|>) :: f a -> f a -> f a
  some :: f a -> f [a]
  many :: f a -> f [a]
  -- Defined in `Control.Applicative'
instance Alternative [] -- Defined in `Control.Applicative'
instance Alternative Maybe -- Defined in `Control.Applicative'

Binary map in Haskell

Is there a two-operand equivalent to map built into Haskell with a type signature of:
map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
The following equivalence should hold:
map2 operator as bs === [operator a b | (a, b) <- zip as bs]
Example:
ghci> map2 (*) [2,3] [4,5]
[8,15]
The function zipWith does what you need. There are also zipWith3 .. zipWith7 for cases with more than two lists.
It's called zipWith.
Here's its type:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Example:
zipWith (*) [2,3] [4,5]
Produces:
[8,15]
I might also recommend that you take a look at Hoogle for such questions in the future. A search for "(a->a->a)->[a]->[a]->[a]" turns up what you were looking for. :)
A more general solution is to use the ZipList instance of Applicative for lists:
let z = (+) <$> ZipList [2,3] <*> ZipList [4,5]
in runZipList z
The nice thing here is that it works with operators of arbitrary arity, so instead of zipWith3 .. zipWith7, you just tack on one more <*> e

Haskell: how to map a tuple?

In Haskell, I can easily map a list:
map (\x -> 2*x) [1,2]
gives me [2,4]. Is there any "mapTuple" function which would work like that?
mapTuple (\x -> 2*x) (1,2)
with the result being (2,4).
Here's a rather short point-free solution:
import Control.Monad (join)
import Control.Arrow ((***))
mapTuple = join (***)
Searching at Hoogle gives no exact matches for (a -> b) -> (a, a) -> (b, b), which is the type you require, but it is pretty easy to do yourself:
mapTuple :: (a -> b) -> (a, a) -> (b, b)
mapTuple f (a1, a2) = (f a1, f a2)
Note, you will have to define a new function for 3-tuples, 4-tuples etc - although such a need might be a sign, that you are not using tuples like they were intended: In general, tuples hold values of different types, so wanting to apply a single function to all values is not very common.
You could use Bifunctor:
import Control.Monad (join)
import Data.Bifunctor (bimap)
join bimap (2*) (1,2)
This works not only for pairs, but for a number of other types as well, e.g. for Either.
Bifunctor is in base as of version 4.8. Previously it was provided by the bifunctors package.
You can also use lens to map tuples:
import Control.Lens
mapPair = over both
Or you can map over tuples with upto 10 elements:
mapNtuple f = traverseOf each (return . f)
You can use arrows from module Control.Arrow to compose functions that work on tuples.
Prelude Control.Arrow> let f = (*2) *** (*2)
Prelude Control.Arrow> f (1,2)
(2,4)
Prelude Control.Arrow> let f' = (*2) *** (*3)
Prelude Control.Arrow> f (2,2)
(4,4)
Prelude Control.Arrow> f' (2,2)
(4,6)
Your mapTuple then becomes
mapTuple f = f *** f
If with your question you asked for a function that maps over tuples of arbitrary arity, then I'm afraid you can't because they would have different types (e.g. the tuple types (a,b) and (a,b,c) are totally different and unrelated).
Here is another way:
mapPair :: (a -> b) -> (a, a) -> (b, b) -- this is the inferred type
mapPair f = uncurry ((,) `on` f)
You need Data.Function imported for on function.
To add another solution to this colourful set... You can also map over arbitrary n-tuples using Scrap-Your-Boilerplate generic programming. For example:
import Data.Data
import Data.Generics.Aliases
double :: Int -> Int
double = (*2)
tuple :: (Int, Int, Int, Int)
tuple = gmapT (mkT double) (1,2,3,4)
Note that the explicit type annotations are important, as SYB selects the fields by type. If one makes one tuple element type Float, for example, it wouldn't be doubled anymore.
Yes, for tuples of 2 items, you can use first and second to map the contents of a tuple (Don't worry about the type signature; a b c can be read as b -> c in this situation). For larger tuples, you should consider using a data structure and lenses instead.
The extra package provides the both function in the Data.Tuple.Extra module. From the docs:
Apply a single function to both components of a pair.
> both succ (1,2) == (2,3)
both :: (a -> b) -> (a, a) -> (b, b)
You can also use Applicatives which have additional benefit of giving you possibility to apply different functions for each tuple element:
import Control.Applicative
mapTuple :: (a -> a') -> (b -> b') -> (a, b) -> (a', b')
mapTuple f g = (,) <$> f . fst <*> g . snd
Inline version:
(\f -> (,) <$> f . fst <*> f . snd) (*2) (3, 4)
or with different map functions and without lambda:
(,) <$> (*2) . fst <*> (*7) . snd $ (3, 4)
Other possibility would be to use Arrows:
import Control.Arrow
(+2) . fst &&& (+2) . snd $ (2, 3)
I just added a package tuples-homogenous-h98 to Hackage that solves this problem. It adds newtype wrappers for tuples and defines Functor, Applicative, Foldable and Traversable instances for them. Using the package you can do things like:
untuple2 . fmap (2 *) . Tuple2 $ (1, 2)
or zip tuples like:
Tuple2 ((+ 1), (*2)) <*> Tuple2 (1, 10)
The uniplate package provides the descend function in the Data.Generics.Uniplate.Data module. This function will apply the function everywhere the types match, so can be applied to lists, tuples, Either, or most other data types. Some examples:
descend (\x -> 2*x) (1,2) == (2,4)
descend (\x -> 2*x) (1,"test",Just 2) == (2,"test",Just 4)
descend (\x -> 2*x) (1,2,3,4,5) == (2,4,6,8,10)
descend (\x -> 2*x) [1,2,3,4,5] == [2,4,6,8,10]
Yes, you would do:
map (\x -> (fst x *2, snd x *2)) [(1,2)]
fst grabs the first data entry in a tuple, and snd grabs the second; so, the line of code says "take a tuple, and return another tuple with the first and second items double the previous."

Resources