I am trying to write a definition for "tabulate", a function that produces the monoidal summary of the values in the given Map that correspond to the keys in the given Foldable collection.
Here is my code:
module Foldables where
import Prelude hiding (Applicative(..), any, concat)
import Data.Foldable
import Data.Semigroup
import qualified Data.Map as Map
import Data.Map (Map)
import Data.Map.Append (AppendMap(..))
import Data.List (intersperse)
import Data.Maybe (maybe)
import Data.Monoid (Any(..), Sum(..))
import GHC.Generics (Generic)
tabulate :: (Ord k, Foldable f, Monoid a) => (v -> a) -> Map k v -> f k -> a
tabulate t m = foldMap (tabulate . k v)
I am getting this error:
src/Foldables.lhs:295:27: error:
• Data constructor not in scope: Tabulate :: b0 -> a
• Perhaps you meant variable ‘tabulate’ (line 295)
src/Foldables.lhs:295:38: error:
Variable not in scope: k :: t0 -> k -> b0
Please don't change anything but what's in the parenthesis on the second line
Update: I think I'm closer to understanding this. Here is my new code. I realize it's incomplete, but it at least compiles.
tabulate :: (Ord k, Foldable f, Monoid a) => (v -> a) -> Map k v -> f k -> a
tabulate t m = foldMap (\x -> mempty maybe [m] maybe map [t])
Now it fails a cabal test:
Falsified (after 2 tests):
<fun>
fromList [(False,'\DC4'),(True,'\1054302')]
[True,True]
No matter what I do seem to get some variation of that
I'm assuming what I need is some kind of conditional in the event the third argument of tabulate isn't mempty?
Here is a hint (that is a solution without
foldMap, which I reckon to be the object of the problem):If I get you correctly, you want to write down something like this:
The case I wrote down is there to work when the intersection of
ks(by the way, a solution withfoldMapwould not need this argument - it will be dropped, as you wanted in the post) with the keys of the map (m) is empty (that is, onlyNothingswere gathered).In other cases, we just fold the container of keys with something, resembling
mappendforMaybe- it first tries to look the given key up in the map. If it succeeds, it puts the result intoJustand thenfmaps the transformationt(which gives us a monoid) into it. If it does not, it returnsNothing. In themappend-sequence ofMaybes allNothings get discarded and the results insideJusts get concatenated withmappend. See the defintion of<>forMaybe(<>isSemigroup's method, which underliesmappendasMonoidisSemigroup's subclass):My solution with
foldMap:It does the following: the function-argument of
foldMaptakes a keyk. If it's not in the map, it returnsmempty. Otherwise - it returnst x, whereJust xis what thelookupgot.