Reputation: 711
I have a couple of Haskell functions for writing to a .tex file (using the HaTeX package) which look like this:
theBody :: Monad m => [ Maybe (String, String)] -> LaTeXT_ m
theBody listOfEntries = do
maketitle
center $ tabular Nothing [RightColumn, VerticalLine, LeftColumn] $ do
textbf "Name" & textbf "Tel"
let removedJusts = map fromJust listOfEntries
map tableEntry removedJusts
tableEntry :: Monad m => (String, String) -> LaTeXT_ m
tableEntry (name, number) = do
lnbk
hline
do
textit (fromString name)
&
textit (fromString number)
When I run this code, I get the following error:
Couldn't match expected type ‘LaTeXT m ()’ with actual type ‘[LaTeXT_ m0]’
Arising from the line where I map the tableEntry
function to my list of tuples. The list of tuples would look something like this:
[("A Name", "12345"), ("Another Name", "54321"), ("Yet Another Name", "98765")]
If I replace map tableEntry removedJusts
with:
tableEntry (removedJusts !! 0)
tableEntry (removedJusts !! 1)
tableEntry (removedJusts !! 2)
It does indeed add these entries to my tex file, so I can't understand why the map function wouldn't work for the list.
Any help appreciated.
Upvotes: 0
Views: 120
Reputation: 34378
tableEntry (removedJusts !! 0)
works because it matches the return type of your theBody
function (LaTeXT_ m
or, expanding the type synonym, LaTeXT m ()
). map tableEntry removedJusts
, on the other hand, gives a list of LaTeXT_ m
, leading to the type error you have seen. What you actually need here is mapM_
, which, in addition to mapping, combines all resulting LaTeXT m ()
computations in a single LaTeXT m ()
:
GHCi> :t mapM_
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
theBody :: Monad m => [ Maybe (String, String)] -> LaTeXT_ m
theBody listOfEntries = do
maketitle
center $ tabular Nothing [RightColumn, VerticalLine, LeftColumn] $ do
textbf "Name" & textbf "Tel"
let removedJusts = map fromJust listOfEntries
mapM_ tableEntry removedJusts
P.S.: A closely related function that you will eventually find useful is traverse
. Unlike mapM_
, traverse
collects, rather than discards, the results of each computation. (Here I used mapM_
becuase you do want to discard said results, as they are merely ()
.)
P.P.S.: Using fromJust
is generally not a good idea. It will make your theBody
crash with a generic error message if there is a Nothing
in the input list. Better options include catMaybes
(from Data.Maybe
), which will silently filter out the Nothing
values (e.g. let removedJusts = catMaybes listOfEntries
), and maybe
and fromMaybe
(the latter also from Data.Maybe
), which allow you to choose how to handle Nothing
values.
Upvotes: 2