Is there a way to use Data.Map
in Haskell to find the number of occurrences in a given list, be it a character or an integer?
For example: [Int] -> Map Int Int
.
If it's possible to achieve, would you be able to do it without the use of fromList
?
CodePudding user response:
You can produce a Map k Int
that acts as a counter for the items in a list with fromListWith :: (Hashable k, Ord k) => (a -> a -> a) -> [(k, a)] -> Map k a
. We can implement such function as:
{-# LANGUAGE TupleSections #-}
import Data.Hashable(Hashable)
import Data.HashMap(Map, fromListWith)
toCounter :: (Hashable a, Ord a) => [a] -> Map a Int
toCounter = fromListWith ( ) . map (,1)
Here we convert each element to a 2-tuple with 1
as the second item of the 2-tuple. In case there is a clash between two keys, we resolve this by summing up the number of times that item occurred.
This produces for example:
ghci> toCounter [1,4,2,5,1,3,0,2]
fromList [(0,1),(1,2),(2,2),(3,1),(4,1),(5,1)]
here for the list [1,4,2,5,1,3,0,2]
0
, 3
, 4
and 5
occur once, and 1
and 2
occur twice.
If it's possible to achieve, would you be able to do it without the use of
fromList
?
Yes, you can work with foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b
and insertWith :: (Hashable k, Ord k) => (a -> a -> a) -> k -> a -> Map k a -> Map k a
. I leave it as an exercise to convert the toCounter
function to a fold pattern.